@codehz/json-expr 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -1
- package/dist/index.d.mts +70 -3
- package/dist/index.mjs +337 -421
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -27,6 +27,27 @@ const PRECEDENCE = {
|
|
|
27
27
|
"**": 11
|
|
28
28
|
};
|
|
29
29
|
const RIGHT_ASSOCIATIVE = new Set(["**"]);
|
|
30
|
+
const BUILTIN_CONSTRUCTORS = new Set([
|
|
31
|
+
"Date",
|
|
32
|
+
"RegExp",
|
|
33
|
+
"URL",
|
|
34
|
+
"URLSearchParams",
|
|
35
|
+
"Map",
|
|
36
|
+
"Set",
|
|
37
|
+
"Int8Array",
|
|
38
|
+
"Uint8Array",
|
|
39
|
+
"Uint8ClampedArray",
|
|
40
|
+
"Int16Array",
|
|
41
|
+
"Uint16Array",
|
|
42
|
+
"Int32Array",
|
|
43
|
+
"Uint32Array",
|
|
44
|
+
"Float32Array",
|
|
45
|
+
"Float64Array",
|
|
46
|
+
"BigInt64Array",
|
|
47
|
+
"BigUint64Array",
|
|
48
|
+
"ArrayBuffer",
|
|
49
|
+
"DataView"
|
|
50
|
+
]);
|
|
30
51
|
var Parser = class Parser {
|
|
31
52
|
pos = 0;
|
|
32
53
|
source;
|
|
@@ -546,41 +567,16 @@ function generate(node) {
|
|
|
546
567
|
return `${node.operator}${arg}`;
|
|
547
568
|
}
|
|
548
569
|
return generate(node.argument) + node.operator;
|
|
549
|
-
case "ConditionalExpr": return `${
|
|
570
|
+
case "ConditionalExpr": return `${wrapIfNeeded(node.test, node, "test")}?${wrapIfNeeded(node.consequent, node, "consequent")}:${wrapIfNeeded(node.alternate, node, "alternate")}`;
|
|
550
571
|
case "MemberExpr": {
|
|
551
572
|
const object = wrapIfNeeded(node.object, node, "object");
|
|
552
|
-
if (node.computed) {
|
|
553
|
-
const property = generate(node.property);
|
|
554
|
-
return node.optional ? `${object}?.[${property}]` : `${object}[${property}]`;
|
|
555
|
-
}
|
|
556
573
|
const property = generate(node.property);
|
|
557
|
-
return node.
|
|
574
|
+
return node.computed ? `${object}${node.optional ? "?." : ""}[${property}]` : `${object}${node.optional ? "?." : "."}${property}`;
|
|
558
575
|
}
|
|
559
576
|
case "CallExpr": {
|
|
560
577
|
const callee = wrapIfNeeded(node.callee, node, "callee");
|
|
561
578
|
const args = node.arguments.map(generate).join(",");
|
|
562
|
-
|
|
563
|
-
"Date",
|
|
564
|
-
"RegExp",
|
|
565
|
-
"URL",
|
|
566
|
-
"URLSearchParams",
|
|
567
|
-
"Map",
|
|
568
|
-
"Set",
|
|
569
|
-
"Int8Array",
|
|
570
|
-
"Uint8Array",
|
|
571
|
-
"Uint8ClampedArray",
|
|
572
|
-
"Int16Array",
|
|
573
|
-
"Uint16Array",
|
|
574
|
-
"Int32Array",
|
|
575
|
-
"Uint32Array",
|
|
576
|
-
"Float32Array",
|
|
577
|
-
"Float64Array",
|
|
578
|
-
"BigInt64Array",
|
|
579
|
-
"BigUint64Array",
|
|
580
|
-
"ArrayBuffer",
|
|
581
|
-
"DataView"
|
|
582
|
-
].includes(node.callee.name)) return node.optional ? `new ${callee}?.(${args})` : `new ${callee}(${args})`;
|
|
583
|
-
return node.optional ? `${callee}?.(${args})` : `${callee}(${args})`;
|
|
579
|
+
return `${node.callee.type === "Identifier" && BUILTIN_CONSTRUCTORS.has(node.callee.name) ? "new " : ""}${callee}${node.optional ? "?." : ""}(${args})`;
|
|
584
580
|
}
|
|
585
581
|
case "ArrayExpr": return `[${node.elements.map(generate).join(",")}]`;
|
|
586
582
|
case "ObjectExpr": return `{${node.properties.map((prop) => {
|
|
@@ -589,10 +585,8 @@ function generate(node) {
|
|
|
589
585
|
}).join(",")}}`;
|
|
590
586
|
case "ArrowFunctionExpr": {
|
|
591
587
|
const params = node.params.map((p) => p.name).join(",");
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
if (node.params.length === 1) return `${params}=>${body}`;
|
|
595
|
-
return `(${params})=>${body}`;
|
|
588
|
+
const body = node.body.type === "ObjectExpr" ? `(${generate(node.body)})` : generate(node.body);
|
|
589
|
+
return `${node.params.length === 1 ? params : `(${params})`}=>${body}`;
|
|
596
590
|
}
|
|
597
591
|
default: {
|
|
598
592
|
const nodeType = node.type ?? "unknown";
|
|
@@ -612,21 +606,32 @@ function wrapIfNeeded(child, parent, position) {
|
|
|
612
606
|
* 判断子节点是否需要括号
|
|
613
607
|
*/
|
|
614
608
|
function needsParens(child, parent, position) {
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
609
|
+
switch (parent.type) {
|
|
610
|
+
case "BinaryExpr":
|
|
611
|
+
if (child.type === "ConditionalExpr" || child.type === "UnaryExpr") return true;
|
|
612
|
+
if (child.type === "BinaryExpr") {
|
|
613
|
+
const childPrec = PRECEDENCE[child.operator] ?? 0;
|
|
614
|
+
const parentPrec = PRECEDENCE[parent.operator] ?? 0;
|
|
615
|
+
if (childPrec < parentPrec) return true;
|
|
616
|
+
if (childPrec === parentPrec && position === "right" && !RIGHT_ASSOCIATIVE.has(parent.operator)) return true;
|
|
617
|
+
}
|
|
618
|
+
return false;
|
|
619
|
+
case "UnaryExpr": return position === "argument" && (child.type === "BinaryExpr" || child.type === "ConditionalExpr");
|
|
620
|
+
case "MemberExpr":
|
|
621
|
+
case "CallExpr":
|
|
622
|
+
if (position !== "object" && position !== "callee") return false;
|
|
623
|
+
if ([
|
|
624
|
+
"BinaryExpr",
|
|
625
|
+
"ConditionalExpr",
|
|
626
|
+
"UnaryExpr",
|
|
627
|
+
"ArrowFunctionExpr",
|
|
628
|
+
"ObjectExpr"
|
|
629
|
+
].includes(child.type)) return true;
|
|
630
|
+
if (child.type === "NumberLiteral" && parent.type === "MemberExpr" && !parent.computed) return !child.raw.includes(".") && !child.raw.includes("e") && !child.raw.includes("x");
|
|
631
|
+
return false;
|
|
632
|
+
case "ConditionalExpr": return position === "test" && child.type === "ConditionalExpr";
|
|
633
|
+
default: return false;
|
|
628
634
|
}
|
|
629
|
-
return false;
|
|
630
635
|
}
|
|
631
636
|
/**
|
|
632
637
|
* 转换 AST 中的标识符
|
|
@@ -733,6 +738,19 @@ function isProxy(obj) {
|
|
|
733
738
|
|
|
734
739
|
//#endregion
|
|
735
740
|
//#region src/proxy-variable.ts
|
|
741
|
+
const typedArrayConstructors = [
|
|
742
|
+
"Int8Array",
|
|
743
|
+
"Uint8Array",
|
|
744
|
+
"Uint8ClampedArray",
|
|
745
|
+
"Int16Array",
|
|
746
|
+
"Uint16Array",
|
|
747
|
+
"Int32Array",
|
|
748
|
+
"Uint32Array",
|
|
749
|
+
"Float32Array",
|
|
750
|
+
"Float64Array",
|
|
751
|
+
"BigInt64Array",
|
|
752
|
+
"BigUint64Array"
|
|
753
|
+
];
|
|
736
754
|
/**
|
|
737
755
|
* 使用 Symbol.description 生成占位符
|
|
738
756
|
* 用于在表达式源码中标识变量
|
|
@@ -741,6 +759,77 @@ function getVariablePlaceholder$1(id) {
|
|
|
741
759
|
return `$$VAR_${id.description}$$`;
|
|
742
760
|
}
|
|
743
761
|
/**
|
|
762
|
+
* 创建标识符 AST 节点
|
|
763
|
+
*/
|
|
764
|
+
function identifier(name) {
|
|
765
|
+
return {
|
|
766
|
+
type: "Identifier",
|
|
767
|
+
name
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* 创建数字字面量 AST 节点
|
|
772
|
+
*/
|
|
773
|
+
function numberLiteral(value) {
|
|
774
|
+
return {
|
|
775
|
+
type: "NumberLiteral",
|
|
776
|
+
value,
|
|
777
|
+
raw: String(value)
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* 创建字符串字面量 AST 节点
|
|
782
|
+
*/
|
|
783
|
+
function stringLiteral(value, quote = "\"") {
|
|
784
|
+
return {
|
|
785
|
+
type: "StringLiteral",
|
|
786
|
+
value,
|
|
787
|
+
quote
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* 创建成员表达式 AST 节点
|
|
792
|
+
*/
|
|
793
|
+
function memberExpr(object, property) {
|
|
794
|
+
return {
|
|
795
|
+
type: "MemberExpr",
|
|
796
|
+
object,
|
|
797
|
+
property,
|
|
798
|
+
computed: false,
|
|
799
|
+
optional: false
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* 创建调用表达式 AST 节点
|
|
804
|
+
*/
|
|
805
|
+
function callExpr(callee, arguments_) {
|
|
806
|
+
return {
|
|
807
|
+
type: "CallExpr",
|
|
808
|
+
callee,
|
|
809
|
+
arguments: arguments_,
|
|
810
|
+
optional: false
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* 创建数组表达式 AST 节点
|
|
815
|
+
*/
|
|
816
|
+
function arrayExpr(elements) {
|
|
817
|
+
return {
|
|
818
|
+
type: "ArrayExpr",
|
|
819
|
+
elements
|
|
820
|
+
};
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* 检查对象是否为 TypedArray 实例
|
|
824
|
+
*/
|
|
825
|
+
function getTypedArrayConstructor(value) {
|
|
826
|
+
for (const constructorName of typedArrayConstructors) {
|
|
827
|
+
const Constructor = globalThis[constructorName];
|
|
828
|
+
if (Constructor && value instanceof Constructor) return Constructor;
|
|
829
|
+
}
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
744
833
|
* 序列化参数为 AST 节点
|
|
745
834
|
* - Proxy Variable/Expression:使用 ast 或占位符标识符
|
|
746
835
|
* - 数组:返回 ArrayExpr 节点
|
|
@@ -753,245 +842,70 @@ function serializeArgumentToAST(arg) {
|
|
|
753
842
|
const meta = getProxyMetadata(arg);
|
|
754
843
|
if (meta) {
|
|
755
844
|
if (meta.ast) return meta.ast;
|
|
756
|
-
if (meta.rootVariable) return
|
|
757
|
-
type: "Identifier",
|
|
758
|
-
name: getVariablePlaceholder$1(meta.rootVariable)
|
|
759
|
-
};
|
|
845
|
+
if (meta.rootVariable) return identifier(getVariablePlaceholder$1(meta.rootVariable));
|
|
760
846
|
}
|
|
761
847
|
}
|
|
762
|
-
if (Array.isArray(arg)) return
|
|
763
|
-
type: "ArrayExpr",
|
|
764
|
-
elements: arg.map(serializeArgumentToAST)
|
|
765
|
-
};
|
|
848
|
+
if (Array.isArray(arg)) return arrayExpr(arg.map(serializeArgumentToAST));
|
|
766
849
|
if (typeof arg === "object" && arg !== null) {
|
|
767
|
-
if (arg instanceof Date) return
|
|
768
|
-
type: "CallExpr",
|
|
769
|
-
callee: {
|
|
770
|
-
type: "Identifier",
|
|
771
|
-
name: "Date"
|
|
772
|
-
},
|
|
773
|
-
arguments: [{
|
|
774
|
-
type: "NumberLiteral",
|
|
775
|
-
value: arg.getTime(),
|
|
776
|
-
raw: String(arg.getTime())
|
|
777
|
-
}],
|
|
778
|
-
optional: false
|
|
779
|
-
};
|
|
850
|
+
if (arg instanceof Date) return callExpr(identifier("Date"), [numberLiteral(arg.getTime())]);
|
|
780
851
|
if (arg instanceof RegExp) {
|
|
781
|
-
const args = [
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
quote: "\""
|
|
785
|
-
}];
|
|
786
|
-
if (arg.flags) args.push({
|
|
787
|
-
type: "StringLiteral",
|
|
788
|
-
value: arg.flags,
|
|
789
|
-
quote: "\""
|
|
790
|
-
});
|
|
791
|
-
return {
|
|
792
|
-
type: "CallExpr",
|
|
793
|
-
callee: {
|
|
794
|
-
type: "Identifier",
|
|
795
|
-
name: "RegExp"
|
|
796
|
-
},
|
|
797
|
-
arguments: args,
|
|
798
|
-
optional: false
|
|
799
|
-
};
|
|
852
|
+
const args = [stringLiteral(arg.source)];
|
|
853
|
+
if (arg.flags) args.push(stringLiteral(arg.flags));
|
|
854
|
+
return callExpr(identifier("RegExp"), args);
|
|
800
855
|
}
|
|
801
|
-
if (typeof URL !== "undefined" && arg instanceof URL) return
|
|
802
|
-
type: "CallExpr",
|
|
803
|
-
callee: {
|
|
804
|
-
type: "Identifier",
|
|
805
|
-
name: "URL"
|
|
806
|
-
},
|
|
807
|
-
arguments: [{
|
|
808
|
-
type: "StringLiteral",
|
|
809
|
-
value: arg.href,
|
|
810
|
-
quote: "\""
|
|
811
|
-
}],
|
|
812
|
-
optional: false
|
|
813
|
-
};
|
|
856
|
+
if (typeof URL !== "undefined" && arg instanceof URL) return callExpr(identifier("URL"), [stringLiteral(arg.href)]);
|
|
814
857
|
if (typeof URLSearchParams !== "undefined" && arg instanceof URLSearchParams) {
|
|
815
858
|
const entries = [];
|
|
816
859
|
arg.forEach((value, key) => {
|
|
817
|
-
entries.push(
|
|
818
|
-
type: "ArrayExpr",
|
|
819
|
-
elements: [{
|
|
820
|
-
type: "StringLiteral",
|
|
821
|
-
value: key,
|
|
822
|
-
quote: "\""
|
|
823
|
-
}, {
|
|
824
|
-
type: "StringLiteral",
|
|
825
|
-
value,
|
|
826
|
-
quote: "\""
|
|
827
|
-
}]
|
|
828
|
-
});
|
|
860
|
+
entries.push(arrayExpr([stringLiteral(key), stringLiteral(value)]));
|
|
829
861
|
});
|
|
830
|
-
return
|
|
831
|
-
type: "CallExpr",
|
|
832
|
-
callee: {
|
|
833
|
-
type: "Identifier",
|
|
834
|
-
name: "URLSearchParams"
|
|
835
|
-
},
|
|
836
|
-
arguments: [{
|
|
837
|
-
type: "ArrayExpr",
|
|
838
|
-
elements: entries
|
|
839
|
-
}],
|
|
840
|
-
optional: false
|
|
841
|
-
};
|
|
862
|
+
return callExpr(identifier("URLSearchParams"), [arrayExpr(entries)]);
|
|
842
863
|
}
|
|
843
864
|
if (arg instanceof Map) {
|
|
844
865
|
const entries = [];
|
|
845
866
|
arg.forEach((value, key) => {
|
|
846
|
-
entries.push(
|
|
847
|
-
type: "ArrayExpr",
|
|
848
|
-
elements: [serializeArgumentToAST(key), serializeArgumentToAST(value)]
|
|
849
|
-
});
|
|
867
|
+
entries.push(arrayExpr([serializeArgumentToAST(key), serializeArgumentToAST(value)]));
|
|
850
868
|
});
|
|
851
|
-
return
|
|
852
|
-
type: "CallExpr",
|
|
853
|
-
callee: {
|
|
854
|
-
type: "Identifier",
|
|
855
|
-
name: "Map"
|
|
856
|
-
},
|
|
857
|
-
arguments: [{
|
|
858
|
-
type: "ArrayExpr",
|
|
859
|
-
elements: entries
|
|
860
|
-
}],
|
|
861
|
-
optional: false
|
|
862
|
-
};
|
|
869
|
+
return callExpr(identifier("Map"), [arrayExpr(entries)]);
|
|
863
870
|
}
|
|
864
871
|
if (arg instanceof Set) {
|
|
865
872
|
const values = [];
|
|
866
|
-
arg.forEach((value) =>
|
|
867
|
-
|
|
868
|
-
});
|
|
869
|
-
return {
|
|
870
|
-
type: "CallExpr",
|
|
871
|
-
callee: {
|
|
872
|
-
type: "Identifier",
|
|
873
|
-
name: "Set"
|
|
874
|
-
},
|
|
875
|
-
arguments: [{
|
|
876
|
-
type: "ArrayExpr",
|
|
877
|
-
elements: values
|
|
878
|
-
}],
|
|
879
|
-
optional: false
|
|
880
|
-
};
|
|
873
|
+
arg.forEach((value) => values.push(serializeArgumentToAST(value)));
|
|
874
|
+
return callExpr(identifier("Set"), [arrayExpr(values)]);
|
|
881
875
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
"Uint16Array",
|
|
888
|
-
"Int32Array",
|
|
889
|
-
"Uint32Array",
|
|
890
|
-
"Float32Array",
|
|
891
|
-
"Float64Array",
|
|
892
|
-
"BigInt64Array",
|
|
893
|
-
"BigUint64Array"
|
|
894
|
-
]) if (typeof globalThis[constructorName] !== "undefined") {
|
|
895
|
-
if (arg instanceof globalThis[constructorName]) {
|
|
896
|
-
const values = [...arg].map((val) => serializeArgumentToAST(val));
|
|
897
|
-
return {
|
|
898
|
-
type: "CallExpr",
|
|
899
|
-
callee: {
|
|
900
|
-
type: "Identifier",
|
|
901
|
-
name: constructorName
|
|
902
|
-
},
|
|
903
|
-
arguments: [{
|
|
904
|
-
type: "ArrayExpr",
|
|
905
|
-
elements: values
|
|
906
|
-
}],
|
|
907
|
-
optional: false
|
|
908
|
-
};
|
|
909
|
-
}
|
|
876
|
+
const typedArrayConstructor = getTypedArrayConstructor(arg);
|
|
877
|
+
if (typedArrayConstructor) {
|
|
878
|
+
const values = [...arg].map(serializeArgumentToAST);
|
|
879
|
+
const constructorName = typedArrayConstructor.name;
|
|
880
|
+
return callExpr(identifier(constructorName), [arrayExpr(values)]);
|
|
910
881
|
}
|
|
911
882
|
if (arg instanceof ArrayBuffer) {
|
|
912
883
|
const uint8Array = new Uint8Array(arg);
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
object: {
|
|
916
|
-
type: "CallExpr",
|
|
917
|
-
callee: {
|
|
918
|
-
type: "Identifier",
|
|
919
|
-
name: "Uint8Array"
|
|
920
|
-
},
|
|
921
|
-
arguments: [{
|
|
922
|
-
type: "ArrayExpr",
|
|
923
|
-
elements: Array.from(uint8Array).map((val) => serializeArgumentToAST(val))
|
|
924
|
-
}],
|
|
925
|
-
optional: false
|
|
926
|
-
},
|
|
927
|
-
property: {
|
|
928
|
-
type: "Identifier",
|
|
929
|
-
name: "buffer"
|
|
930
|
-
},
|
|
931
|
-
computed: false,
|
|
932
|
-
optional: false
|
|
933
|
-
};
|
|
884
|
+
const values = Array.from(uint8Array).map(numberLiteral);
|
|
885
|
+
return memberExpr(callExpr(identifier("Uint8Array"), [arrayExpr(values)]), identifier("buffer"));
|
|
934
886
|
}
|
|
935
|
-
if (arg instanceof DataView) return
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
887
|
+
if (arg instanceof DataView) return callExpr(identifier("DataView"), [serializeArgumentToAST(arg.buffer)]);
|
|
888
|
+
return {
|
|
889
|
+
type: "ObjectExpr",
|
|
890
|
+
properties: Object.entries(arg).map(([k, v]) => {
|
|
891
|
+
return {
|
|
892
|
+
key: /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? identifier(k) : stringLiteral(k),
|
|
893
|
+
value: serializeArgumentToAST(v),
|
|
894
|
+
computed: false,
|
|
895
|
+
shorthand: false
|
|
896
|
+
};
|
|
897
|
+
})
|
|
943
898
|
};
|
|
944
899
|
}
|
|
945
|
-
if (typeof arg === "object" && arg !== null) return {
|
|
946
|
-
type: "ObjectExpr",
|
|
947
|
-
properties: Object.entries(arg).map(([k, v]) => {
|
|
948
|
-
return {
|
|
949
|
-
key: /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(k) ? {
|
|
950
|
-
type: "Identifier",
|
|
951
|
-
name: k
|
|
952
|
-
} : {
|
|
953
|
-
type: "StringLiteral",
|
|
954
|
-
value: k,
|
|
955
|
-
quote: "\""
|
|
956
|
-
},
|
|
957
|
-
value: serializeArgumentToAST(v),
|
|
958
|
-
computed: false,
|
|
959
|
-
shorthand: false
|
|
960
|
-
};
|
|
961
|
-
})
|
|
962
|
-
};
|
|
963
900
|
if (arg === null) return { type: "NullLiteral" };
|
|
964
|
-
if (arg === void 0) return
|
|
965
|
-
type: "Identifier",
|
|
966
|
-
name: "undefined"
|
|
967
|
-
};
|
|
901
|
+
if (arg === void 0) return identifier("undefined");
|
|
968
902
|
if (typeof arg === "boolean") return {
|
|
969
903
|
type: "BooleanLiteral",
|
|
970
904
|
value: arg
|
|
971
905
|
};
|
|
972
|
-
if (typeof arg === "number") return
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
raw: String(arg)
|
|
976
|
-
};
|
|
977
|
-
if (typeof arg === "string") return {
|
|
978
|
-
type: "StringLiteral",
|
|
979
|
-
value: arg,
|
|
980
|
-
quote: "\""
|
|
981
|
-
};
|
|
982
|
-
if (typeof arg === "bigint") return {
|
|
983
|
-
type: "CallExpr",
|
|
984
|
-
callee: {
|
|
985
|
-
type: "Identifier",
|
|
986
|
-
name: "BigInt"
|
|
987
|
-
},
|
|
988
|
-
arguments: [{
|
|
989
|
-
type: "StringLiteral",
|
|
990
|
-
value: arg.toString(),
|
|
991
|
-
quote: "\""
|
|
992
|
-
}],
|
|
993
|
-
optional: false
|
|
994
|
-
};
|
|
906
|
+
if (typeof arg === "number") return numberLiteral(arg);
|
|
907
|
+
if (typeof arg === "string") return stringLiteral(arg);
|
|
908
|
+
if (typeof arg === "bigint") return callExpr(identifier("BigInt"), [stringLiteral(arg.toString())]);
|
|
995
909
|
throw new Error(`Unsupported argument type: ${typeof arg}`);
|
|
996
910
|
}
|
|
997
911
|
/**
|
|
@@ -1007,6 +921,31 @@ function collectDepsFromArgs(args, deps) {
|
|
|
1007
921
|
}
|
|
1008
922
|
}
|
|
1009
923
|
/**
|
|
924
|
+
* 根据路径构建成员表达式 AST
|
|
925
|
+
*/
|
|
926
|
+
function buildMemberExprAst(rootId, path) {
|
|
927
|
+
let ast = identifier(getVariablePlaceholder$1(rootId));
|
|
928
|
+
for (const prop of path) ast = memberExpr(ast, identifier(prop));
|
|
929
|
+
return ast;
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* 创建 Proxy 的公共 handler
|
|
933
|
+
*/
|
|
934
|
+
function createProxyHandler(ast, deps) {
|
|
935
|
+
return {
|
|
936
|
+
get(_target, prop) {
|
|
937
|
+
if (typeof prop === "symbol") return void 0;
|
|
938
|
+
return createProxyExpressionWithAST(memberExpr(ast, identifier(String(prop))), deps);
|
|
939
|
+
},
|
|
940
|
+
apply(_target, _thisArg, args) {
|
|
941
|
+
const callAst = callExpr(ast, args.map(serializeArgumentToAST));
|
|
942
|
+
const newDeps = new Set(deps);
|
|
943
|
+
collectDepsFromArgs(args, newDeps);
|
|
944
|
+
return createProxyExpressionWithAST(callAst, newDeps);
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
/**
|
|
1010
949
|
* 创建根 Variable Proxy
|
|
1011
950
|
* 拦截属性访问,返回新的 expression proxy
|
|
1012
951
|
* 不可直接调用(apply 应该只在链式调用后可用)
|
|
@@ -1019,7 +958,7 @@ function createProxyVariable(id) {
|
|
|
1019
958
|
const proxy = new Proxy(function() {}, {
|
|
1020
959
|
get(_target, prop) {
|
|
1021
960
|
if (typeof prop === "symbol") return void 0;
|
|
1022
|
-
return
|
|
961
|
+
return createProxyExpressionWithAST(buildMemberExprAst(id, [String(prop)]), deps);
|
|
1023
962
|
},
|
|
1024
963
|
apply() {
|
|
1025
964
|
throw new Error("Variable cannot be called directly");
|
|
@@ -1034,57 +973,6 @@ function createProxyVariable(id) {
|
|
|
1034
973
|
return proxy;
|
|
1035
974
|
}
|
|
1036
975
|
/**
|
|
1037
|
-
* 创建属性访问后的 Proxy
|
|
1038
|
-
* 继续拦截属性访问(链式访问)
|
|
1039
|
-
* 拦截 apply 进行方法调用
|
|
1040
|
-
*
|
|
1041
|
-
* @param rootId - 根变量的 Symbol
|
|
1042
|
-
* @param path - 属性访问路径
|
|
1043
|
-
* @param deps - 依赖集合
|
|
1044
|
-
* @returns Proxy 包装的 Expression
|
|
1045
|
-
*/
|
|
1046
|
-
function createProxyExpression(rootId, path, deps) {
|
|
1047
|
-
let ast = {
|
|
1048
|
-
type: "Identifier",
|
|
1049
|
-
name: getVariablePlaceholder$1(rootId)
|
|
1050
|
-
};
|
|
1051
|
-
for (const prop of path) ast = {
|
|
1052
|
-
type: "MemberExpr",
|
|
1053
|
-
object: ast,
|
|
1054
|
-
property: {
|
|
1055
|
-
type: "Identifier",
|
|
1056
|
-
name: prop
|
|
1057
|
-
},
|
|
1058
|
-
computed: false,
|
|
1059
|
-
optional: false
|
|
1060
|
-
};
|
|
1061
|
-
const proxy = new Proxy(function() {}, {
|
|
1062
|
-
get(_target, prop) {
|
|
1063
|
-
if (typeof prop === "symbol") return void 0;
|
|
1064
|
-
return createProxyExpression(rootId, [...path, String(prop)], deps);
|
|
1065
|
-
},
|
|
1066
|
-
apply(_target, _thisArg, args) {
|
|
1067
|
-
const callAst = {
|
|
1068
|
-
type: "CallExpr",
|
|
1069
|
-
callee: ast,
|
|
1070
|
-
arguments: args.map(serializeArgumentToAST),
|
|
1071
|
-
optional: false
|
|
1072
|
-
};
|
|
1073
|
-
const newDeps = new Set(deps);
|
|
1074
|
-
collectDepsFromArgs(args, newDeps);
|
|
1075
|
-
return createProxyExpressionWithAST(callAst, newDeps);
|
|
1076
|
-
}
|
|
1077
|
-
});
|
|
1078
|
-
setProxyMetadata(proxy, {
|
|
1079
|
-
type: "expression",
|
|
1080
|
-
path,
|
|
1081
|
-
rootVariable: rootId,
|
|
1082
|
-
ast,
|
|
1083
|
-
dependencies: deps
|
|
1084
|
-
});
|
|
1085
|
-
return proxy;
|
|
1086
|
-
}
|
|
1087
|
-
/**
|
|
1088
976
|
* 创建带完整 AST 的 Proxy(方法调用后)
|
|
1089
977
|
* 可以继续链式访问和调用
|
|
1090
978
|
*
|
|
@@ -1093,32 +981,7 @@ function createProxyExpression(rootId, path, deps) {
|
|
|
1093
981
|
* @returns Proxy 包装的 Expression
|
|
1094
982
|
*/
|
|
1095
983
|
function createProxyExpressionWithAST(ast, deps) {
|
|
1096
|
-
const proxy = new Proxy(function() {},
|
|
1097
|
-
get(_target, prop) {
|
|
1098
|
-
if (typeof prop === "symbol") return void 0;
|
|
1099
|
-
return createProxyExpressionWithAST({
|
|
1100
|
-
type: "MemberExpr",
|
|
1101
|
-
object: ast,
|
|
1102
|
-
property: {
|
|
1103
|
-
type: "Identifier",
|
|
1104
|
-
name: String(prop)
|
|
1105
|
-
},
|
|
1106
|
-
computed: false,
|
|
1107
|
-
optional: false
|
|
1108
|
-
}, deps);
|
|
1109
|
-
},
|
|
1110
|
-
apply(_target, _thisArg, args) {
|
|
1111
|
-
const callAst = {
|
|
1112
|
-
type: "CallExpr",
|
|
1113
|
-
callee: ast,
|
|
1114
|
-
arguments: args.map(serializeArgumentToAST),
|
|
1115
|
-
optional: false
|
|
1116
|
-
};
|
|
1117
|
-
const newDeps = new Set(deps);
|
|
1118
|
-
collectDepsFromArgs(args, newDeps);
|
|
1119
|
-
return createProxyExpressionWithAST(callAst, newDeps);
|
|
1120
|
-
}
|
|
1121
|
-
});
|
|
984
|
+
const proxy = new Proxy(function() {}, createProxyHandler(ast, deps));
|
|
1122
985
|
setProxyMetadata(proxy, {
|
|
1123
986
|
type: "expression",
|
|
1124
987
|
path: [],
|
|
@@ -1234,30 +1097,29 @@ function compile(expression, variables, options = {}) {
|
|
|
1234
1097
|
const ast = serializeArgumentToAST(expression);
|
|
1235
1098
|
const variableOrder = [];
|
|
1236
1099
|
const variableToIndex = /* @__PURE__ */ new Map();
|
|
1237
|
-
for (const name of Object.keys(variables)) if (!variableToIndex.has(name)) {
|
|
1238
|
-
variableToIndex.set(name, variableOrder.length);
|
|
1239
|
-
variableOrder.push(name);
|
|
1240
|
-
}
|
|
1241
1100
|
const descToName = /* @__PURE__ */ new Map();
|
|
1242
1101
|
for (const [name, value] of Object.entries(variables)) {
|
|
1102
|
+
if (!variableToIndex.has(name)) {
|
|
1103
|
+
variableToIndex.set(name, variableOrder.length);
|
|
1104
|
+
variableOrder.push(name);
|
|
1105
|
+
}
|
|
1243
1106
|
const id = getVariableId(value);
|
|
1244
|
-
if (id
|
|
1107
|
+
if (id?.description) descToName.set(id.description, name);
|
|
1245
1108
|
}
|
|
1246
1109
|
const undefinedVars = [];
|
|
1247
1110
|
const transformed = transformIdentifiers(ast, (name) => {
|
|
1248
1111
|
const placeholderMatch = name.match(/^\$\$VAR_(.+)\$\$$/);
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
if (!varName) throw new Error(`Unknown variable placeholder: ${name}`);
|
|
1253
|
-
name = varName;
|
|
1254
|
-
}
|
|
1255
|
-
const index = variableToIndex.get(name);
|
|
1112
|
+
const resolvedName = placeholderMatch ? descToName.get(placeholderMatch[1]) : name;
|
|
1113
|
+
if (placeholderMatch && !resolvedName) throw new Error(`Unknown variable placeholder: ${name}`);
|
|
1114
|
+
const index = variableToIndex.get(resolvedName);
|
|
1256
1115
|
if (index !== void 0) return `$${index}`;
|
|
1257
|
-
if (!ALLOWED_GLOBALS.has(
|
|
1258
|
-
return
|
|
1116
|
+
if (!ALLOWED_GLOBALS.has(resolvedName)) undefinedVars.push(resolvedName);
|
|
1117
|
+
return resolvedName;
|
|
1259
1118
|
});
|
|
1260
|
-
if (undefinedVars.length > 0)
|
|
1119
|
+
if (undefinedVars.length > 0) {
|
|
1120
|
+
const uniqueVars = [...new Set(undefinedVars)];
|
|
1121
|
+
throw new Error(`Undefined variable(s): ${uniqueVars.join(", ")}`);
|
|
1122
|
+
}
|
|
1261
1123
|
const expressions = [];
|
|
1262
1124
|
if (shortCircuit) {
|
|
1263
1125
|
let nextIndex = variableOrder.length;
|
|
@@ -1265,26 +1127,20 @@ function compile(expression, variables, options = {}) {
|
|
|
1265
1127
|
if (node.type === "BinaryExpr" && (node.operator === "||" || node.operator === "&&" || node.operator === "??")) return compileShortCircuit(node);
|
|
1266
1128
|
if (node.type === "ConditionalExpr") return compileConditional(node);
|
|
1267
1129
|
const exprStr = generate(node);
|
|
1268
|
-
const idx = nextIndex++;
|
|
1269
1130
|
expressions.push(exprStr);
|
|
1270
|
-
return
|
|
1131
|
+
return nextIndex++;
|
|
1271
1132
|
}
|
|
1272
1133
|
function compileShortCircuit(node) {
|
|
1273
1134
|
const leftIdx = compileAst(node.left);
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
case "&&":
|
|
1280
|
-
branchCondition = `!$${leftIdx}`;
|
|
1281
|
-
break;
|
|
1282
|
-
default: branchCondition = `$${leftIdx}!=null`;
|
|
1283
|
-
}
|
|
1135
|
+
const branchConditions = {
|
|
1136
|
+
"||": `$${leftIdx}`,
|
|
1137
|
+
"&&": `!$${leftIdx}`,
|
|
1138
|
+
"??": `$${leftIdx}!=null`
|
|
1139
|
+
};
|
|
1284
1140
|
const branchIdx = expressions.length;
|
|
1285
1141
|
expressions.push([
|
|
1286
1142
|
"br",
|
|
1287
|
-
|
|
1143
|
+
branchConditions[node.operator],
|
|
1288
1144
|
0
|
|
1289
1145
|
]);
|
|
1290
1146
|
nextIndex++;
|
|
@@ -1388,16 +1244,14 @@ function evaluate(data, values) {
|
|
|
1388
1244
|
*/
|
|
1389
1245
|
function buildEvaluatorFunctionBody(expressions, variableCount) {
|
|
1390
1246
|
if (expressions.length === 0) throw new Error("No expressions to evaluate");
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
lines.push(`return $values[$values.length - 1];`);
|
|
1400
|
-
return lines.join("\n");
|
|
1247
|
+
return [
|
|
1248
|
+
...Array.from({ length: variableCount }, (_, i) => `const $${i} = $values[${i}];`),
|
|
1249
|
+
...expressions.map((expr, i) => {
|
|
1250
|
+
const idx = variableCount + i;
|
|
1251
|
+
return `const $${idx} = ${expr}; $values[${idx}] = $${idx};`;
|
|
1252
|
+
}),
|
|
1253
|
+
`return $values[$values.length - 1];`
|
|
1254
|
+
].join("\n");
|
|
1401
1255
|
}
|
|
1402
1256
|
/**
|
|
1403
1257
|
* 构造带控制流支持的求值函数体(V2 格式)
|
|
@@ -1408,39 +1262,38 @@ function buildEvaluatorFunctionBody(expressions, variableCount) {
|
|
|
1408
1262
|
*/
|
|
1409
1263
|
function buildEvaluatorFunctionBodyV2(expressions, variableCount) {
|
|
1410
1264
|
if (expressions.length === 0) throw new Error("No expressions to evaluate");
|
|
1411
|
-
const lines = [
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1265
|
+
const lines = [
|
|
1266
|
+
...Array.from({ length: variableCount }, (_, i) => `const $${i} = $values[${i}];`),
|
|
1267
|
+
"let $pc = 0;",
|
|
1268
|
+
"let $lastValue;",
|
|
1269
|
+
...expressions.map((_, i) => `let $${variableCount + i};`),
|
|
1270
|
+
`while ($pc < ${expressions.length}) {`,
|
|
1271
|
+
" switch ($pc) {"
|
|
1272
|
+
];
|
|
1273
|
+
expressions.forEach((expr, i) => {
|
|
1420
1274
|
const idx = variableCount + i;
|
|
1421
1275
|
lines.push(` case ${i}: {`);
|
|
1422
1276
|
if (typeof expr === "string") {
|
|
1423
|
-
lines.push(` $${idx} = ${expr};`);
|
|
1277
|
+
lines.push(` $${idx} = $lastValue = ${expr};`);
|
|
1424
1278
|
lines.push(` $values[${idx}] = $${idx};`);
|
|
1425
|
-
lines.push(
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1279
|
+
lines.push(" $pc++; break;");
|
|
1280
|
+
} else {
|
|
1281
|
+
const [type] = expr;
|
|
1282
|
+
switch (type) {
|
|
1283
|
+
case "br":
|
|
1284
|
+
lines.push(` if (${expr[1]}) { $pc += ${expr[2] + 1}; } else { $pc++; } break;`);
|
|
1285
|
+
break;
|
|
1286
|
+
case "jmp":
|
|
1287
|
+
lines.push(` $pc += ${expr[1] + 1}; break;`);
|
|
1288
|
+
break;
|
|
1289
|
+
case "phi":
|
|
1290
|
+
lines.push(` $${idx} = $values[${idx}] = $lastValue; $pc++; break;`);
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1438
1293
|
}
|
|
1439
|
-
lines.push(
|
|
1440
|
-
}
|
|
1441
|
-
lines.push(
|
|
1442
|
-
lines.push(`}`);
|
|
1443
|
-
lines.push(`return $values[$values.length - 1];`);
|
|
1294
|
+
lines.push(" }");
|
|
1295
|
+
});
|
|
1296
|
+
lines.push(" }", "}", "return $values[$values.length - 1];");
|
|
1444
1297
|
return lines.join("\n");
|
|
1445
1298
|
}
|
|
1446
1299
|
|
|
@@ -1550,6 +1403,20 @@ function createLambdaParam(index) {
|
|
|
1550
1403
|
*/
|
|
1551
1404
|
function lambda(builder) {
|
|
1552
1405
|
const paramCount = builder.length;
|
|
1406
|
+
const { params, paramSymbols } = createLambdaParams(paramCount);
|
|
1407
|
+
const { bodyAst, bodyDeps } = extractBodyAstAndDeps(builder(...params));
|
|
1408
|
+
const lambdaProxy = createProxyExpressionWithAST(createArrowFunctionAst(transformParamPlaceholders(bodyAst, paramSymbols), paramCount), filterClosureDeps(bodyDeps, paramSymbols));
|
|
1409
|
+
const existingMeta = getProxyMetadata(lambdaProxy);
|
|
1410
|
+
if (existingMeta) setProxyMetadata(lambdaProxy, {
|
|
1411
|
+
...existingMeta,
|
|
1412
|
+
type: "expression"
|
|
1413
|
+
});
|
|
1414
|
+
return lambdaProxy;
|
|
1415
|
+
}
|
|
1416
|
+
/**
|
|
1417
|
+
* 创建 lambda 参数和符号映射
|
|
1418
|
+
*/
|
|
1419
|
+
function createLambdaParams(paramCount) {
|
|
1553
1420
|
const params = [];
|
|
1554
1421
|
const paramSymbols = [];
|
|
1555
1422
|
for (let i = 0; i < paramCount; i++) {
|
|
@@ -1558,19 +1425,34 @@ function lambda(builder) {
|
|
|
1558
1425
|
const meta = getProxyMetadata(param);
|
|
1559
1426
|
if (meta?.rootVariable) paramSymbols.push(meta.rootVariable);
|
|
1560
1427
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1428
|
+
return {
|
|
1429
|
+
params,
|
|
1430
|
+
paramSymbols
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* 从表达式中提取 AST 和依赖
|
|
1435
|
+
*/
|
|
1436
|
+
function extractBodyAstAndDeps(bodyExpr) {
|
|
1564
1437
|
const meta = (typeof bodyExpr === "object" || typeof bodyExpr === "function") && bodyExpr !== null ? getProxyMetadata(bodyExpr) : void 0;
|
|
1565
|
-
if (meta?.ast) {
|
|
1566
|
-
bodyAst
|
|
1567
|
-
bodyDeps
|
|
1568
|
-
}
|
|
1569
|
-
|
|
1570
|
-
bodyDeps = /* @__PURE__ */ new Set();
|
|
1438
|
+
if (meta?.ast) return {
|
|
1439
|
+
bodyAst: meta.ast,
|
|
1440
|
+
bodyDeps: meta.dependencies ?? /* @__PURE__ */ new Set()
|
|
1441
|
+
};
|
|
1442
|
+
else {
|
|
1443
|
+
const bodyDeps = /* @__PURE__ */ new Set();
|
|
1571
1444
|
collectDepsFromArgs([bodyExpr], bodyDeps);
|
|
1445
|
+
return {
|
|
1446
|
+
bodyAst: serializeArgumentToAST(bodyExpr),
|
|
1447
|
+
bodyDeps
|
|
1448
|
+
};
|
|
1572
1449
|
}
|
|
1573
|
-
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
* 将参数占位符标识符转换为实际参数名
|
|
1453
|
+
*/
|
|
1454
|
+
function transformParamPlaceholders(bodyAst, paramSymbols) {
|
|
1455
|
+
return transformIdentifiers(bodyAst, (name) => {
|
|
1574
1456
|
for (let i = 0; i < paramSymbols.length; i++) {
|
|
1575
1457
|
const sym = paramSymbols[i];
|
|
1576
1458
|
if (!sym) continue;
|
|
@@ -1578,23 +1460,27 @@ function lambda(builder) {
|
|
|
1578
1460
|
}
|
|
1579
1461
|
return name;
|
|
1580
1462
|
});
|
|
1581
|
-
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* 创建箭头函数 AST
|
|
1466
|
+
*/
|
|
1467
|
+
function createArrowFunctionAst(bodyAst, paramCount) {
|
|
1468
|
+
return {
|
|
1582
1469
|
type: "ArrowFunctionExpr",
|
|
1583
|
-
params:
|
|
1470
|
+
params: Array.from({ length: paramCount }, (_, i) => ({
|
|
1584
1471
|
type: "Identifier",
|
|
1585
1472
|
name: `_${i}`
|
|
1586
1473
|
})),
|
|
1587
|
-
body:
|
|
1474
|
+
body: bodyAst
|
|
1588
1475
|
};
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* 过滤掉 lambda 参数依赖,只保留外部闭包变量
|
|
1479
|
+
*/
|
|
1480
|
+
function filterClosureDeps(bodyDeps, paramSymbols) {
|
|
1589
1481
|
const closureDeps = /* @__PURE__ */ new Set();
|
|
1590
1482
|
for (const dep of bodyDeps) if (!paramSymbols.includes(dep)) closureDeps.add(dep);
|
|
1591
|
-
|
|
1592
|
-
const existingMeta = getProxyMetadata(lambdaProxy);
|
|
1593
|
-
if (existingMeta) setProxyMetadata(lambdaProxy, {
|
|
1594
|
-
...existingMeta,
|
|
1595
|
-
type: "expression"
|
|
1596
|
-
});
|
|
1597
|
-
return lambdaProxy;
|
|
1483
|
+
return closureDeps;
|
|
1598
1484
|
}
|
|
1599
1485
|
|
|
1600
1486
|
//#endregion
|
|
@@ -1647,5 +1533,35 @@ function t(strings, ...values) {
|
|
|
1647
1533
|
}
|
|
1648
1534
|
|
|
1649
1535
|
//#endregion
|
|
1650
|
-
|
|
1536
|
+
//#region src/wrap.ts
|
|
1537
|
+
/**
|
|
1538
|
+
* 将静态值包装为 Proxy Expression
|
|
1539
|
+
* 返回的 Proxy 可以像 Variable 一样调用方法和访问属性
|
|
1540
|
+
*
|
|
1541
|
+
* @template T - 值的类型
|
|
1542
|
+
* @param value - 要包装的静态值(支持原始值、对象、数组、Date、RegExp 等)
|
|
1543
|
+
* @returns Proxy Expression,可以继续链式调用
|
|
1544
|
+
*
|
|
1545
|
+
* @example
|
|
1546
|
+
* ```ts
|
|
1547
|
+
* // 包装 RegExp
|
|
1548
|
+
* const pattern = wrap(/^[a-z]+$/i);
|
|
1549
|
+
* const input = variable<string>();
|
|
1550
|
+
* const result = pattern.match(input);
|
|
1551
|
+
*
|
|
1552
|
+
* // 包装 Date
|
|
1553
|
+
* const now = wrap(new Date());
|
|
1554
|
+
* const year = now.getFullYear();
|
|
1555
|
+
*
|
|
1556
|
+
* // 包装数组
|
|
1557
|
+
* const numbers = wrap([1, 2, 3, 4, 5]);
|
|
1558
|
+
* const doubled = numbers.map((x) => x * 2);
|
|
1559
|
+
* ```
|
|
1560
|
+
*/
|
|
1561
|
+
function wrap(value) {
|
|
1562
|
+
return createProxyExpressionWithAST(serializeArgumentToAST(value), /* @__PURE__ */ new Set());
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
//#endregion
|
|
1566
|
+
export { compile, evaluate, expr, getVariableId, isProxy, isProxyExpression, isProxyVariable, lambda, t, variable, wrap };
|
|
1651
1567
|
//# sourceMappingURL=index.mjs.map
|