jsxpression 0.1.38 → 0.1.41
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/CHANGELOG.md +8 -0
- package/lib/analyze/analysis-error.d.ts +1 -1
- package/lib/analyze/analysis-error.d.ts.map +1 -1
- package/lib/analyze/analysis-report.d.ts.map +1 -1
- package/lib/analyze/analysis-report.js.map +1 -1
- package/lib/analyze/data/analyze.d.ts +2 -2
- package/lib/analyze/data/analyze.d.ts.map +1 -1
- package/lib/analyze/data/data-access.d.ts +1 -1
- package/lib/analyze/data/data-access.d.ts.map +1 -1
- package/lib/analyze/data/method-calls.d.ts +1 -1
- package/lib/analyze/data/method-calls.d.ts.map +1 -1
- package/lib/analyze/data/utils.d.ts +3 -3
- package/lib/analyze/data/utils.d.ts.map +1 -1
- package/lib/analyze/jsx/analyze.d.ts +2 -2
- package/lib/analyze/jsx/analyze.d.ts.map +1 -1
- package/lib/analyze/jsx/element-attributes.js.map +1 -1
- package/lib/analyze/jsx/element-children.js +5 -6
- package/lib/analyze/jsx/element-children.js.map +1 -1
- package/lib/analyze/security/analyze.d.ts +2 -2
- package/lib/analyze/security/analyze.d.ts.map +1 -1
- package/lib/analyze/security/analyze.js +2 -1
- package/lib/analyze/security/analyze.js.map +1 -1
- package/lib/analyze/security/expressions.d.ts +1 -1
- package/lib/analyze/security/expressions.d.ts.map +1 -1
- package/lib/analyze/security/identifiers.js.map +1 -1
- package/lib/analyze/validation-context.d.ts.map +1 -1
- package/lib/codegen/builtins/builtin-types.js.map +1 -1
- package/lib/codegen/generate-typescript-definitions.d.ts +1 -1
- package/lib/codegen/generate-typescript-definitions.d.ts.map +1 -1
- package/lib/codegen/generate-typescript-definitions.js +6 -1
- package/lib/codegen/generate-typescript-definitions.js.map +1 -1
- package/lib/codegen/schema/component-types.js.map +1 -1
- package/lib/codegen/schema/data-types.js.map +1 -1
- package/lib/codegen/schema/function-types.d.ts.map +1 -1
- package/lib/codegen/schema/function-types.js +3 -1
- package/lib/codegen/schema/function-types.js.map +1 -1
- package/lib/codegen/schema/utils.d.ts +1 -1
- package/lib/codegen/schema/utils.d.ts.map +1 -1
- package/lib/codegen/schema/utils.js +1 -1
- package/lib/codegen/schema/utils.js.map +1 -1
- package/lib/compile/compilation-error.d.ts.map +1 -1
- package/lib/compile/compile.js.map +1 -1
- package/lib/evaluate/evaluate.js +2 -2
- package/lib/evaluate/evaluate.js.map +1 -1
- package/lib/evaluate/evaluation-error.d.ts.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/parse/parse-error.d.ts.map +1 -1
- package/lib/render.d.ts +2 -2
- package/lib/render.d.ts.map +1 -1
- package/lib/render.js.map +1 -1
- package/lib/schema.js.map +1 -1
- package/lib/traverse.d.ts.map +1 -1
- package/lib/traverse.js +0 -1
- package/lib/traverse.js.map +1 -1
- package/lib/validate.d.ts +1 -1
- package/lib/validate.d.ts.map +1 -1
- package/lib/validate.js.map +1 -1
- package/package.json +2 -2
- package/src/analyze/analysis-error.ts +1 -1
- package/src/analyze/analyze.test.ts +8 -6
- package/src/analyze/data/analyze.ts +2 -2
- package/src/analyze/data/data-access.ts +1 -1
- package/src/analyze/data/method-calls.ts +1 -1
- package/src/analyze/data/utils.ts +3 -3
- package/src/analyze/jsx/analyze.ts +2 -2
- package/src/analyze/jsx/element-attributes.ts +1 -1
- package/src/analyze/jsx/element-children.ts +5 -5
- package/src/analyze/security/analyze.ts +4 -4
- package/src/analyze/security/expressions.ts +1 -1
- package/src/analyze/security/identifiers.ts +3 -3
- package/src/builtins.ts +1 -1
- package/src/codegen/generate-typescript-definitions.test.ts +27 -27
- package/src/codegen/generate-typescript-definitions.ts +7 -2
- package/src/codegen/schema/function-types.ts +4 -2
- package/src/codegen/schema/utils.ts +3 -3
- package/src/compile/compile.ts +15 -15
- package/src/evaluate/evaluate.test.ts +19 -19
- package/src/evaluate/evaluate.ts +2 -2
- package/src/index.ts +1 -1
- package/src/render.test.ts +5 -2
- package/src/render.ts +4 -3
- package/src/schema.ts +1 -1
- package/src/traverse.ts +12 -13
- package/src/validate.ts +1 -1
|
@@ -60,7 +60,7 @@ describe("evaluate", () => {
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
expect(result.props
|
|
63
|
+
expect(result.props.value).toBe(15); // floor(5 * 3.14159...) = 15
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
it("should throw EvaluationError for unknown component", () => {
|
|
@@ -116,7 +116,7 @@ describe("evaluate", () => {
|
|
|
116
116
|
expect(result.type).toBe("Outer");
|
|
117
117
|
expect(result.props).toEqual({ x: 10 });
|
|
118
118
|
expect(result.children).toHaveLength(1);
|
|
119
|
-
const innerNode = result.children[0]
|
|
119
|
+
const innerNode = result.children[0];
|
|
120
120
|
expect(innerNode.type).toBe("Inner");
|
|
121
121
|
expect(innerNode.props).toEqual({ y: 20 });
|
|
122
122
|
expect(innerNode.children).toEqual(["Text"]);
|
|
@@ -159,7 +159,7 @@ describe("evaluate", () => {
|
|
|
159
159
|
},
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
-
expect(result.props
|
|
162
|
+
expect(result.props.msg).toBe("visible");
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
it("should evaluate array methods on props", () => {
|
|
@@ -176,7 +176,7 @@ describe("evaluate", () => {
|
|
|
176
176
|
},
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
-
expect(result.props
|
|
179
|
+
expect(result.props.values).toEqual([6, 8, 10]);
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
it("should handle runtime errors gracefully", () => {
|
|
@@ -208,7 +208,7 @@ describe("evaluate", () => {
|
|
|
208
208
|
},
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
-
expect(result.props
|
|
211
|
+
expect(result.props.msg).toBe("Anonymous");
|
|
212
212
|
});
|
|
213
213
|
|
|
214
214
|
it("should flatten and filter children correctly", () => {
|
|
@@ -269,7 +269,7 @@ describe("evaluate", () => {
|
|
|
269
269
|
}
|
|
270
270
|
);
|
|
271
271
|
|
|
272
|
-
expect(result.props
|
|
272
|
+
expect(result.props.values).toBe("6, 8, 10");
|
|
273
273
|
});
|
|
274
274
|
|
|
275
275
|
it("should pass correct parameters to custom createElement", () => {
|
|
@@ -295,7 +295,7 @@ describe("evaluate", () => {
|
|
|
295
295
|
components: { Test: TestComponent },
|
|
296
296
|
});
|
|
297
297
|
|
|
298
|
-
expect(result.props
|
|
298
|
+
expect(result.props.msg).toBe("Hello World");
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
it("should handle numeric operations", () => {
|
|
@@ -310,7 +310,7 @@ describe("evaluate", () => {
|
|
|
310
310
|
components: { Test: TestComponent },
|
|
311
311
|
});
|
|
312
312
|
|
|
313
|
-
expect(result.props
|
|
313
|
+
expect(result.props.value).toBe(11); // 5 + (3 * 2)
|
|
314
314
|
});
|
|
315
315
|
|
|
316
316
|
it("should handle data access in children", () => {
|
|
@@ -340,7 +340,7 @@ describe("evaluate", () => {
|
|
|
340
340
|
components: { Test: TestComponent },
|
|
341
341
|
});
|
|
342
342
|
|
|
343
|
-
expect(result.props
|
|
343
|
+
expect(result.props.value).toBe(42);
|
|
344
344
|
});
|
|
345
345
|
|
|
346
346
|
it("should evaluate const with computed expression", () => {
|
|
@@ -355,7 +355,7 @@ describe("evaluate", () => {
|
|
|
355
355
|
components: { Test: TestComponent },
|
|
356
356
|
});
|
|
357
357
|
|
|
358
|
-
expect(result.props
|
|
358
|
+
expect(result.props.value).toBe(8); // (3+1)*2
|
|
359
359
|
});
|
|
360
360
|
|
|
361
361
|
it("should evaluate const referencing data", () => {
|
|
@@ -370,7 +370,7 @@ describe("evaluate", () => {
|
|
|
370
370
|
components: { Test: TestComponent },
|
|
371
371
|
});
|
|
372
372
|
|
|
373
|
-
expect(result.props
|
|
373
|
+
expect(result.props.msg).toBe("Hello World");
|
|
374
374
|
});
|
|
375
375
|
|
|
376
376
|
it("should evaluate const with computed array", () => {
|
|
@@ -388,7 +388,7 @@ describe("evaluate", () => {
|
|
|
388
388
|
}
|
|
389
389
|
);
|
|
390
390
|
|
|
391
|
-
expect(result.props
|
|
391
|
+
expect(result.props.count).toBe(3);
|
|
392
392
|
});
|
|
393
393
|
});
|
|
394
394
|
|
|
@@ -425,7 +425,7 @@ describe("evaluate", () => {
|
|
|
425
425
|
}
|
|
426
426
|
);
|
|
427
427
|
|
|
428
|
-
expect(result.props
|
|
428
|
+
expect(result.props.result).toBe(10);
|
|
429
429
|
});
|
|
430
430
|
|
|
431
431
|
it("should evaluate nested user-defined components", () => {
|
|
@@ -450,8 +450,8 @@ describe("evaluate", () => {
|
|
|
450
450
|
|
|
451
451
|
expect(result.type).toBe("Div");
|
|
452
452
|
expect(result.children).toHaveLength(1);
|
|
453
|
-
expect(
|
|
454
|
-
expect(
|
|
453
|
+
expect(result.children[0].type).toBe("Span");
|
|
454
|
+
expect(result.children[0].children).toEqual(["hi"]);
|
|
455
455
|
});
|
|
456
456
|
|
|
457
457
|
it("should evaluate function with children", () => {
|
|
@@ -476,7 +476,7 @@ describe("evaluate", () => {
|
|
|
476
476
|
|
|
477
477
|
expect(result.type).toBe("Div");
|
|
478
478
|
expect(result.children).toHaveLength(1);
|
|
479
|
-
expect(
|
|
479
|
+
expect(result.children[0].type).toBe("Span");
|
|
480
480
|
});
|
|
481
481
|
|
|
482
482
|
it("should evaluate function with default parameter values", () => {
|
|
@@ -530,7 +530,7 @@ describe("evaluate", () => {
|
|
|
530
530
|
}
|
|
531
531
|
);
|
|
532
532
|
|
|
533
|
-
expect(result.props
|
|
533
|
+
expect(result.props.result).toBe(12);
|
|
534
534
|
});
|
|
535
535
|
|
|
536
536
|
it("should evaluate function used in map with const", () => {
|
|
@@ -571,7 +571,7 @@ describe("evaluate", () => {
|
|
|
571
571
|
components: { Test: TestComponent },
|
|
572
572
|
});
|
|
573
573
|
|
|
574
|
-
expect(result.props
|
|
574
|
+
expect(result.props.value).toBe("42");
|
|
575
575
|
});
|
|
576
576
|
|
|
577
577
|
it("should evaluate String() with boolean", () => {
|
|
@@ -586,7 +586,7 @@ describe("evaluate", () => {
|
|
|
586
586
|
components: { Test: TestComponent },
|
|
587
587
|
});
|
|
588
588
|
|
|
589
|
-
expect(result.props
|
|
589
|
+
expect(result.props.value).toBe("true");
|
|
590
590
|
});
|
|
591
591
|
});
|
|
592
592
|
});
|
package/src/evaluate/evaluate.ts
CHANGED
|
@@ -48,7 +48,7 @@ export function evaluate<T = any>(source: string, schema: Schema, options: Evalu
|
|
|
48
48
|
const h = createH(components, createElement || defaultCreateElement, schema);
|
|
49
49
|
const frozen = deepFreezeData(structuredClone(data));
|
|
50
50
|
try {
|
|
51
|
-
//
|
|
51
|
+
// oxlint-disable-next-line typescript/no-implied-eval, no-new-func
|
|
52
52
|
return new Function("h", "Math", ...dataKeys, ...functionKeys, source)(
|
|
53
53
|
h,
|
|
54
54
|
Math,
|
|
@@ -88,7 +88,7 @@ function createH(components: ComponentDict, createElement: CreateElement, schema
|
|
|
88
88
|
|
|
89
89
|
if (!Component) {
|
|
90
90
|
if (isElementAllowed(schema, type)) {
|
|
91
|
-
const defaultComponent = (props: PropsDict): any => (canHaveChildren(schema, type) ? props
|
|
91
|
+
const defaultComponent = (props: PropsDict): any => (canHaveChildren(schema, type) ? props["children"] : null);
|
|
92
92
|
return createElement(defaultComponent, props, ...children.flat().filter(Boolean));
|
|
93
93
|
}
|
|
94
94
|
|
package/src/index.ts
CHANGED
package/src/render.test.ts
CHANGED
|
@@ -248,13 +248,16 @@ describe("render", () => {
|
|
|
248
248
|
).toThrow(ParseError);
|
|
249
249
|
});
|
|
250
250
|
|
|
251
|
-
it("should propagate
|
|
251
|
+
it("should propagate EvaluationError for disallowed identifiers (analyzeIdentifiers disabled)", () => {
|
|
252
252
|
const TestComponent = (): TestNode => ({
|
|
253
253
|
type: "Test",
|
|
254
254
|
props: {},
|
|
255
255
|
children: [],
|
|
256
256
|
});
|
|
257
257
|
|
|
258
|
+
// analyzeIdentifiers is currently disabled in analyze.ts, so bare property access on an
|
|
259
|
+
// undeclared global like `window` is no longer caught at analysis time — it now fails at
|
|
260
|
+
// evaluation time instead, once the identifier turns out to be undefined at runtime.
|
|
258
261
|
expect(() =>
|
|
259
262
|
render(
|
|
260
263
|
"<Text>{window.location}</Text>",
|
|
@@ -269,7 +272,7 @@ describe("render", () => {
|
|
|
269
272
|
components: { Text: TestComponent },
|
|
270
273
|
}
|
|
271
274
|
)
|
|
272
|
-
).toThrow(
|
|
275
|
+
).toThrow(EvaluationError);
|
|
273
276
|
});
|
|
274
277
|
|
|
275
278
|
it("should propagate AnalysisError for unknown JSX elements", () => {
|
package/src/render.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { compile as compileInternal } from "./compile/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import type { EvaluateOptions } from "./evaluate/evaluate.js";
|
|
3
|
+
import { evaluate } from "./evaluate/evaluate.js";
|
|
3
4
|
import { parse } from "./parse/index.js";
|
|
4
|
-
import { Schema } from "./schema.js";
|
|
5
|
+
import type { Schema } from "./schema.js";
|
|
5
6
|
import { analyze, AnalysisError } from "./analyze/index.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -71,7 +72,7 @@ export function render<T = any>(
|
|
|
71
72
|
throw AnalysisError.fromReport(report);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
return evaluate(compileInternal(ast), schema, options)
|
|
75
|
+
return evaluate(compileInternal(ast), schema, options);
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
export function compile<T = any>(source: string, schema: Schema, { minSeverity = 3 }: RenderOptions<T> = {}): string {
|
package/src/schema.ts
CHANGED
|
@@ -161,7 +161,7 @@ export function deserializePropertySchemaFromJson(json: string): PropertySchema
|
|
|
161
161
|
return undefined;
|
|
162
162
|
}
|
|
163
163
|
const validated = zodSchema.safeParse(parsed);
|
|
164
|
-
if(!validated.success) {
|
|
164
|
+
if (!validated.success) {
|
|
165
165
|
return undefined;
|
|
166
166
|
}
|
|
167
167
|
return validated.data;
|
package/src/traverse.ts
CHANGED
|
@@ -103,55 +103,54 @@ const tsNodeTypes = [
|
|
|
103
103
|
|
|
104
104
|
const tsWalkers: Record<string, (node: any, state: any, c: any) => void> = {};
|
|
105
105
|
for (const nodeType of tsNodeTypes) {
|
|
106
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
107
106
|
tsWalkers[nodeType] = () => {};
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
const jsxWalkers: ExtendedRecursiveVisitors = {
|
|
111
110
|
JSXElement(node, state, visit) {
|
|
112
|
-
const element = node
|
|
111
|
+
const element = node;
|
|
113
112
|
visit(element.openingElement, state);
|
|
114
113
|
for (const child of element.children) {
|
|
115
114
|
if (isJsxText(child) || isJsxEmptyExpression(child)) {
|
|
116
115
|
continue;
|
|
117
116
|
}
|
|
118
|
-
visit(child
|
|
117
|
+
visit(child, state);
|
|
119
118
|
}
|
|
120
119
|
},
|
|
121
120
|
|
|
122
121
|
JSXFragment(node, state, visit) {
|
|
123
|
-
const fragment = node
|
|
122
|
+
const fragment = node;
|
|
124
123
|
for (const child of fragment.children) {
|
|
125
124
|
if (isJsxText(child) || isJsxEmptyExpression(child)) {
|
|
126
125
|
continue;
|
|
127
126
|
}
|
|
128
|
-
visit(child
|
|
127
|
+
visit(child, state);
|
|
129
128
|
}
|
|
130
129
|
},
|
|
131
130
|
|
|
132
131
|
JSXOpeningElement(node, state, visit) {
|
|
133
|
-
const opening = node
|
|
132
|
+
const opening = node;
|
|
134
133
|
for (const attr of opening.attributes) {
|
|
135
|
-
visit(attr
|
|
134
|
+
visit(attr, state);
|
|
136
135
|
}
|
|
137
136
|
},
|
|
138
137
|
|
|
139
138
|
JSXAttribute(node, state, visit) {
|
|
140
|
-
const attr = node
|
|
139
|
+
const attr = node;
|
|
141
140
|
if (attr.value) {
|
|
142
|
-
visit(attr.value
|
|
141
|
+
visit(attr.value, state);
|
|
143
142
|
}
|
|
144
143
|
},
|
|
145
144
|
|
|
146
145
|
JSXSpreadAttribute(node, state, visit) {
|
|
147
|
-
const spread = node
|
|
148
|
-
visit(spread.argument
|
|
146
|
+
const spread = node;
|
|
147
|
+
visit(spread.argument, state);
|
|
149
148
|
},
|
|
150
149
|
|
|
151
150
|
JSXExpressionContainer(node, state, visit) {
|
|
152
|
-
const container = node
|
|
151
|
+
const container = node;
|
|
153
152
|
if (!isJsxEmptyExpression(container.expression)) {
|
|
154
|
-
visit(container.expression
|
|
153
|
+
visit(container.expression, state);
|
|
155
154
|
}
|
|
156
155
|
},
|
|
157
156
|
};
|
package/src/validate.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { analyze, AnalysisError } from "./analyze/index.js";
|
|
2
2
|
import { parse, ParseError } from "./parse/index.js";
|
|
3
|
-
import { Schema } from "./schema.js";
|
|
3
|
+
import type { Schema } from "./schema.js";
|
|
4
4
|
|
|
5
5
|
export type ValidateResult = { ok: true } | { ok: false; error: AnalysisError | ParseError };
|
|
6
6
|
|