expression-language
Version:
Javascript implementation of symfony/expression-language
180 lines (179 loc) • 7.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _Expression = _interopRequireDefault(require("./Expression"));
var _Node = _interopRequireDefault(require("./Node/Node"));
var _ConstantNode = _interopRequireDefault(require("./Node/ConstantNode"));
var _NameNode = _interopRequireDefault(require("./Node/NameNode"));
var _FunctionNode = _interopRequireDefault(require("./Node/FunctionNode"));
var _UnaryNode = _interopRequireDefault(require("./Node/UnaryNode"));
var _BinaryNode = _interopRequireDefault(require("./Node/BinaryNode"));
var _GetAttrNode = _interopRequireDefault(require("./Node/GetAttrNode"));
var _ArrayNode = _interopRequireDefault(require("./Node/ArrayNode"));
var _ArgumentsNode = _interopRequireDefault(require("./Node/ArgumentsNode"));
var _ConditionalNode = _interopRequireDefault(require("./Node/ConditionalNode"));
var _NullCoalesceNode = _interopRequireDefault(require("./Node/NullCoalesceNode"));
var _NullCoalescedNameNode = _interopRequireDefault(require("./Node/NullCoalescedNameNode"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class ParsedExpression extends _Expression.default {
constructor(expression, nodes) {
super(expression);
_defineProperty(this, "getNodes", () => {
return this.nodes;
});
this.nodes = nodes;
}
static fromJSON(json) {
const obj = typeof json === 'string' ? JSON.parse(json) : json;
const buildNode = n => {
if (n === null || n === undefined) {
return n;
}
// If it's already an instance (unlikely when parsing from plain JSON), return as-is
if (n instanceof _Node.default) {
return n;
}
// If it doesn't look like a Node, return as-is
if (typeof n !== 'object' || !n.name) {
return n;
}
switch (n.name) {
case 'ConstantNode':
{
return new _ConstantNode.default(n.attributes?.value, !!n.isIdentifier, !!n.isNullSafe);
}
case 'NameNode':
{
return new _NameNode.default(n.attributes?.name);
}
case 'NullCoalescedNameNode':
{
return new _NullCoalescedNameNode.default(n.attributes?.name);
}
case 'UnaryNode':
{
return new _UnaryNode.default(n.attributes?.operator, buildNode(n.nodes?.node));
}
case 'BinaryNode':
{
return new _BinaryNode.default(n.attributes?.operator, buildNode(n.nodes?.left), buildNode(n.nodes?.right));
}
case 'ConditionalNode':
{
return new _ConditionalNode.default(buildNode(n.nodes?.expr1), buildNode(n.nodes?.expr2), buildNode(n.nodes?.expr3));
}
case 'NullCoalesceNode':
{
return new _NullCoalesceNode.default(buildNode(n.nodes?.expr1), buildNode(n.nodes?.expr2));
}
case 'ArgumentsNode':
{
const argsNode = new _ArgumentsNode.default();
// Preserve internal state if present
if (typeof n.type === 'string') argsNode.type = n.type;
if (typeof n.index === 'number') argsNode.index = n.index;
if (typeof n.keyIndex === 'number') argsNode.keyIndex = n.keyIndex;
argsNode.nodes = {};
for (const key of Object.keys(n.nodes || {})) {
argsNode.nodes[key] = buildNode(n.nodes[key]);
}
return argsNode;
}
case 'ArrayNode':
{
const arrNode = new _ArrayNode.default();
if (typeof n.type === 'string') arrNode.type = n.type;
if (typeof n.index === 'number') arrNode.index = n.index;
if (typeof n.keyIndex === 'number') arrNode.keyIndex = n.keyIndex;
arrNode.nodes = {};
for (const key of Object.keys(n.nodes || {})) {
arrNode.nodes[key] = buildNode(n.nodes[key]);
}
return arrNode;
}
case 'FunctionNode':
{
const args = buildNode(n.nodes?.arguments);
return new _FunctionNode.default(n.attributes?.name, args);
}
case 'GetAttrNode':
{
const node = new _GetAttrNode.default(buildNode(n.nodes?.node), buildNode(n.nodes?.attribute), buildNode(n.nodes?.fnArguments), n.attributes?.type);
// restore flags if present
if (n.attributes && typeof n.attributes.is_null_coalesce === 'boolean') {
node.attributes.is_null_coalesce = n.attributes.is_null_coalesce;
}
if (n.attributes && typeof n.attributes.is_short_circuited === 'boolean') {
node.attributes.is_short_circuited = n.attributes.is_short_circuited;
}
return node;
}
case 'Node':
{
// Generic container Node used by Parser for argument lists
const generic = new _Node.default();
if (Array.isArray(n.nodes)) {
// Convert array to object with numeric keys to match original
generic.nodes = n.nodes.map(buildNode);
} else {
generic.nodes = {};
for (const key of Object.keys(n.nodes || {})) {
generic.nodes[key] = buildNode(n.nodes[key]);
}
}
// Restore attributes if any
generic.attributes = n.attributes || {};
return generic;
}
default:
{
// Fallback: try to reconstruct as a generic Node
const generic = new _Node.default();
generic.name = n.name;
// children
if (Array.isArray(n.nodes)) {
generic.nodes = n.nodes.map(buildNode);
} else {
generic.nodes = {};
for (const key of Object.keys(n.nodes || {})) {
generic.nodes[key] = buildNode(n.nodes[key]);
}
}
generic.attributes = n.attributes || {};
return generic;
}
}
};
const buildNodesContainer = nodesData => {
if (nodesData === null || nodesData === undefined) {
return nodesData;
}
// Single node object
if (nodesData.name) {
return buildNode(nodesData);
}
// Array of nodes
if (Array.isArray(nodesData)) {
return nodesData.map(buildNode);
}
// Object map of nodes
if (typeof nodesData === 'object') {
const out = {};
for (const key of Object.keys(nodesData)) {
out[key] = buildNode(nodesData[key]);
}
return out;
}
return nodesData;
};
const expression = obj.expression;
const nodes = buildNodesContainer(obj.nodes);
return new ParsedExpression(expression, nodes);
}
}
exports.default = ParsedExpression;