diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index 547cf9343..872b32244 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -310,6 +310,92 @@ function cxjs_right(s,l) if (s == null || l == null) return null; return s.substr(s.length-l); } + +function cxjs_eval(_context, _this, expr, permflags, cur_obj_name, par_obj_name) + { + console.log(_context, _this, expr, permflags, cur_obj_name, par_obj_name); + if (expr === null || expr === undefined) return null; + const expr_str = String(expr).trim(); + if (expr_str === '') return null; + + const first_char = expr_str.charAt(0); + const last_char = expr_str.charAt(expr_str.length - 1); + + // Eval boolean and null literals. + const expr_lower = expr_str.toLowerCase(); + if (expr_lower === 'true') return true; + if (expr_lower === 'false') return false; + if (expr_lower === 'null') return null; + + // Eval integer. + if (/^-?\d+$/.test(expr_str)) + return parseInt(expr_str, 10); + + // Eval floating point. + if (/^-?\d+\.\d*$/.test(expr_str) || /^-?\d*\.\d+$/.test(expr_str)) + return parseFloat(expr_str); + + // Eval double-quoted string. + if (expr_str.length >= 2 && first_char === '"' && last_char === '"') + return expr_str.substring(1, expr_str.length - 1); + + // Eval single-quoted string. + if (expr_str.length >= 2 && first_char === "'" && last_char === "'") + return expr_str.substring(1, expr_str.length - 1); + + // Eval :property, ::property, or :object:property + if (first_char === ':') + { + const rest = expr_str.substring(1); + const colon2 = rest.indexOf(':'); + if (colon2 < 0) + { + // :property - current object reference + if (!permflags || permflags.indexOf('C') >= 0) + { + if (cur_obj_name !== null && cur_obj_name !== undefined) + { + const cur_node = wgtrGetNode(_context, cur_obj_name); + if (cur_node) return wgtrGetProperty(cur_node, rest); + } + else if (_this !== null && _this !== undefined) + { + return (wgtrIsNode(_this)) + ? wgtrGetProperty(_this, rest) + : (_this[rest] ?? null); + } + } + } + else if (colon2 < 1) + { + // ::property - parent object reference (C's ParentID) + if (!permflags || permflags.indexOf('P') >= 0) + { + const prop = rest.substring(1); + const par_node = (par_obj_name !== null && par_obj_name !== undefined) + ? wgtrGetNode(_context, par_obj_name) + : wgtrGetParent(_this); + if (par_node) return wgtrGetProperty(par_node, prop); + } + } + else + { + // :object:property - named object reference + if (_context != null && (!permflags || permflags.indexOf('O') >= 0)) + { + const objname = rest.substring(0, colon2); + const propname = rest.substring(colon2 + 1); + const obj = wgtrGetNode(_context, objname); + if (obj) return wgtrGetProperty(obj, propname); + } + } + } + + console.warn("Failed to eval expression: \"" + expr_str + "\""); + + return null; + } + function cxjs_isnull(v,d) { if (v == null) diff --git a/centrallix/expression/exp_generator.c b/centrallix/expression/exp_generator.c index fc521a39d..0b34a243e 100644 --- a/centrallix/expression/exp_generator.c +++ b/centrallix/expression/exp_generator.c @@ -457,7 +457,7 @@ exp_internal_GenerateText_js(pExpression exp, pExpGen eg) return -1; } exp_internal_WriteText(eg, eg->TmpBuf); - if (!strcmp(exp->Name, "substitute")) + if (!strcmp(exp->Name, "substitute") || !strcmp(exp->Name, "eval")) { /** This function requires awareness of its object/property scope **/ exp_internal_WriteText(eg, "_context,_this,");