@xaendar/compiler 0.7.28 → 0.7.30
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/dist/xaendar-compiler.es.js +54 -22
- package/package.json +3 -3
|
@@ -342,12 +342,45 @@ var GLOBAL_IDENTIFIERS = /* @__PURE__ */ new Set([
|
|
|
342
342
|
"Window"
|
|
343
343
|
]);
|
|
344
344
|
var ROOT_NODE = "root";
|
|
345
|
+
/**
|
|
346
|
+
* Resolves references to component properties inside a template expression.
|
|
347
|
+
*
|
|
348
|
+
* Identifiers that are not found in the active scope chain and are not
|
|
349
|
+
* well-known globals are prefixed with `this.` so they resolve against
|
|
350
|
+
* the component instance at runtime. Identifiers found in the scope chain
|
|
351
|
+
* are resolved either as a bare local reference (if declared directly in
|
|
352
|
+
* the current generated function's own scope) or via a runtime
|
|
353
|
+
* `parentContext.get(...)` traversal (if inherited from an enclosing
|
|
354
|
+
* scope) — and a trailing `()` is appended in either case if the
|
|
355
|
+
* identifier was declared as a signal, so the generated code always
|
|
356
|
+
* correctly unwraps it.
|
|
357
|
+
*
|
|
358
|
+
* The original formatting of the expression — parentheses, spacing,
|
|
359
|
+
* operator tokens, member access dots — is preserved verbatim by delegating
|
|
360
|
+
* to `node.getText()` for any subtree that contains no resolvable identifiers.
|
|
361
|
+
*
|
|
362
|
+
* @param expression - Either a raw identifier string or a validated
|
|
363
|
+
* `Expression` node produced by `validateExpression`.
|
|
364
|
+
* @param compilerContext - The active template scope context.
|
|
365
|
+
* @returns The resolved expression as a JavaScript string ready for codegen.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* // Simple identifier
|
|
369
|
+
* resolveExpression('items', context) // → 'this.items'
|
|
370
|
+
*
|
|
371
|
+
* @example
|
|
372
|
+
* // Signal identifier inherited from an ancestor scope (e.g. `$index` in a
|
|
373
|
+
* // nested @for body)
|
|
374
|
+
* resolveExpression('$index', context) // → "parentContext.get('$index')()"
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* // Complex expression — formatting preserved
|
|
378
|
+
* resolveExpression(node, context)
|
|
379
|
+
* // typeof id !== 'boolean' || pippo instanceof HTMLElement
|
|
380
|
+
* // → typeof this.id !== 'boolean' || this.pippo instanceof HTMLElement
|
|
381
|
+
*/
|
|
345
382
|
function resolveExpression(expression, compilerContext, options) {
|
|
346
|
-
|
|
347
|
-
let actualOptions;
|
|
348
|
-
if (compilerContext instanceof CompilerContext) actualCompilerContext = compilerContext;
|
|
349
|
-
else actualOptions = compilerContext;
|
|
350
|
-
return emitNode(expression, expression, actualCompilerContext, mapDefaultOptions(actualOptions));
|
|
383
|
+
return emitNode(expression, expression, compilerContext, mapDefaultOptions(options));
|
|
351
384
|
}
|
|
352
385
|
/**
|
|
353
386
|
* Emits the resolved text for a node.
|
|
@@ -2879,17 +2912,17 @@ var Parser = class {
|
|
|
2879
2912
|
* emitted as bare statements, validated in place.
|
|
2880
2913
|
*/
|
|
2881
2914
|
function typeCheckElement(node, processNode, context) {
|
|
2882
|
-
const lines =
|
|
2915
|
+
const lines = new Array();
|
|
2883
2916
|
node.attributes.forEach(({ value }) => {
|
|
2884
|
-
if (typeof value !== "string") lines.push(`${resolveExpression(value.expression, { resolver: "root" })};`);
|
|
2917
|
+
if (typeof value !== "string") lines.push(`${resolveExpression(value.expression, context, { resolver: "root" })};`);
|
|
2885
2918
|
});
|
|
2886
2919
|
node.events.forEach(({ handler, parameters }) => {
|
|
2887
|
-
const
|
|
2920
|
+
const eventContext = new CompilerContext([], context);
|
|
2921
|
+
eventContext.addUnresolvableIdentifier("$event");
|
|
2922
|
+
const args = parameters.map((parameter) => resolveExpression(parameter, eventContext, { resolver: "root" })).join(", ");
|
|
2888
2923
|
lines.push(`root.${handler}(${args});`);
|
|
2889
2924
|
});
|
|
2890
|
-
node.children.forEach((child
|
|
2891
|
-
lines.push(...processNode(child, context));
|
|
2892
|
-
});
|
|
2925
|
+
node.children.forEach((child) => lines.push(...processNode(child, context)));
|
|
2893
2926
|
return lines;
|
|
2894
2927
|
}
|
|
2895
2928
|
//#endregion
|
|
@@ -2919,7 +2952,7 @@ function typeCheckFor(node, processNode, context) {
|
|
|
2919
2952
|
oddName,
|
|
2920
2953
|
node.itemAlias
|
|
2921
2954
|
].forEach((identifier) => forContext.addUnresolvableIdentifier(identifier));
|
|
2922
|
-
const lines =
|
|
2955
|
+
const lines = new Array();
|
|
2923
2956
|
lines.push(`for (const ${node.itemAlias} of root.${node.iterableSource}) {`);
|
|
2924
2957
|
lines.push(...indent([
|
|
2925
2958
|
`let ${indexName}!: number;`,
|
|
@@ -2927,8 +2960,8 @@ function typeCheckFor(node, processNode, context) {
|
|
|
2927
2960
|
`let ${lastName}!: boolean;`,
|
|
2928
2961
|
`let ${evenName}!: boolean;`,
|
|
2929
2962
|
`let ${oddName}!: boolean;`,
|
|
2930
|
-
`${resolveExpression(node.trackExpression, { skipResolution: true })};`,
|
|
2931
|
-
...node.children.flatMap((child) => processNode(child,
|
|
2963
|
+
`${resolveExpression(node.trackExpression, context, { skipResolution: true })};`,
|
|
2964
|
+
...node.children.flatMap((child) => processNode(child, forContext))
|
|
2932
2965
|
]));
|
|
2933
2966
|
lines.push("}");
|
|
2934
2967
|
return lines;
|
|
@@ -2962,14 +2995,14 @@ function resolveImplicit(node, implicit) {
|
|
|
2962
2995
|
* flat sibling functions could never express.
|
|
2963
2996
|
*/
|
|
2964
2997
|
function typeCheckIf(node, processNode, context) {
|
|
2965
|
-
const lines =
|
|
2966
|
-
const condition = resolveExpression(node.conditionNode, { resolver: "root" });
|
|
2998
|
+
const lines = new Array();
|
|
2999
|
+
const condition = resolveExpression(node.conditionNode, context, { resolver: "root" });
|
|
2967
3000
|
lines.push(`if (${condition}) {`);
|
|
2968
3001
|
lines.push(...indent(node.children.flatMap((child) => processNode(child, context))));
|
|
2969
3002
|
lines.push("}");
|
|
2970
3003
|
let alt = node.alternate;
|
|
2971
3004
|
while (alt?.type === ASTNodeType.ElseIf) {
|
|
2972
|
-
const elseIfCondition = resolveExpression(alt.conditionNode, { resolver: "root" });
|
|
3005
|
+
const elseIfCondition = resolveExpression(alt.conditionNode, context, { resolver: "root" });
|
|
2973
3006
|
lines.push(`else if (${elseIfCondition}) {`);
|
|
2974
3007
|
lines.push(...indent(alt.children.flatMap((child) => processNode(child, context))));
|
|
2975
3008
|
lines.push("}");
|
|
@@ -3000,7 +3033,7 @@ function typeCheckIf(node, processNode, context) {
|
|
|
3000
3033
|
* JS/TS fallthrough syntax directly.
|
|
3001
3034
|
*/
|
|
3002
3035
|
function typeCheckSwitch(node, processNode, context) {
|
|
3003
|
-
const lines = [`switch (${resolveExpression(node.expression, { resolver: "root" })}) {`];
|
|
3036
|
+
const lines = [`switch (${resolveExpression(node.expression, context, { resolver: "root" })}) {`];
|
|
3004
3037
|
node.children.forEach((caseNode) => {
|
|
3005
3038
|
caseNode.condition?.length ? caseNode.condition.forEach((conditionValue) => lines.push(` case ${conditionValue}:`)) : lines.push(" default:");
|
|
3006
3039
|
lines.push(...indent(indent([...caseNode.children.flatMap((child) => processNode(child, context)), "break;"])));
|
|
@@ -3017,8 +3050,8 @@ function typeCheckSwitch(node, processNode, context) {
|
|
|
3017
3050
|
* interpolation's expression is emitted as a bare statement — enough for
|
|
3018
3051
|
* TS to validate it, with no name needing to be bound to the result.
|
|
3019
3052
|
*/
|
|
3020
|
-
function typeCheckTextAndInterpolation(node, _processNode,
|
|
3021
|
-
return node.type === ASTNodeType.Interpolation ? [`${resolveExpression(node.expression, { resolver: "root" })};`] : [];
|
|
3053
|
+
function typeCheckTextAndInterpolation(node, _processNode, context) {
|
|
3054
|
+
return node.type === ASTNodeType.Interpolation ? [`${resolveExpression(node.expression, context, { resolver: "root" })};`] : [];
|
|
3022
3055
|
}
|
|
3023
3056
|
//#endregion
|
|
3024
3057
|
//#region ../packages/compiler/src/type-checker/type-checker.ts
|
|
@@ -3068,10 +3101,9 @@ var TypeChecker = class {
|
|
|
3068
3101
|
* relevant if the consuming project has `noUnusedLocals` enabled.
|
|
3069
3102
|
*/
|
|
3070
3103
|
generate() {
|
|
3071
|
-
const body = this._ast.flatMap((node) => this._processNode(node));
|
|
3072
3104
|
return [
|
|
3073
3105
|
"function typeCheck() {",
|
|
3074
|
-
...indent(
|
|
3106
|
+
...indent(this._ast.flatMap((node) => this._processNode(node))),
|
|
3075
3107
|
"}"
|
|
3076
3108
|
].join("\n");
|
|
3077
3109
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.30",
|
|
4
4
|
"description": "A library for transpiling Xaendar Templates into JavaScript code",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@xaendar/common": "0.7.
|
|
20
|
-
"@xaendar/types": "0.7.
|
|
19
|
+
"@xaendar/common": "0.7.30",
|
|
20
|
+
"@xaendar/types": "0.7.30",
|
|
21
21
|
"typescript": "^6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|