@mintjamsinc/ichigojs 0.1.55 → 0.1.56
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/ichigo.cjs +59 -23
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +59 -23
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.min.cjs +1 -1
- package/dist/ichigo.umd.js +59 -23
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/util/ExpressionUtils.d.ts +10 -2
- package/package.json +1 -1
package/dist/ichigo.esm.js
CHANGED
|
@@ -6731,11 +6731,18 @@ class ExpressionUtils {
|
|
|
6731
6731
|
* Extracts variable and function names used in the expression.
|
|
6732
6732
|
* @param expression The expression string to analyze.
|
|
6733
6733
|
* @param functionDependencies A dictionary mapping function names to their dependencies.
|
|
6734
|
+
* @param options Optional parsing options.
|
|
6735
|
+
* - asScript: If true, parse the input as a Script (allows multi-statement source with semicolons,
|
|
6736
|
+
* declarations, control-flow, etc.). If false/omitted, parse as a single expression (the default,
|
|
6737
|
+
* for backward compatibility with interpolation and binding directives).
|
|
6734
6738
|
* @returns An array of identifier names.
|
|
6735
6739
|
*/
|
|
6736
|
-
static extractIdentifiers(expression, functionDependencies) {
|
|
6740
|
+
static extractIdentifiers(expression, functionDependencies, options) {
|
|
6737
6741
|
const identifiers = new Set();
|
|
6738
|
-
|
|
6742
|
+
// In expression mode we wrap in parens so acorn parses the source as a single expression.
|
|
6743
|
+
// In script mode we parse as a Program so that multi-statement bodies (e.g. "a=1; b=2") work.
|
|
6744
|
+
const source = options?.asScript ? expression : `(${expression})`;
|
|
6745
|
+
const ast = parse(source, { ecmaVersion: "latest" });
|
|
6739
6746
|
// Use walk.full instead of walk.simple to visit ALL nodes including assignment LHS
|
|
6740
6747
|
full(ast, (node) => {
|
|
6741
6748
|
if (node.type === 'Identifier') {
|
|
@@ -6967,10 +6974,10 @@ class ExpressionUtils {
|
|
|
6967
6974
|
* @param identifiers The list of identifiers that are available in bindings.
|
|
6968
6975
|
* @returns The rewritten expression.
|
|
6969
6976
|
*/
|
|
6970
|
-
static rewriteExpression(expression, identifiers) {
|
|
6977
|
+
static rewriteExpression(expression, identifiers, options) {
|
|
6971
6978
|
// Reserved words and built-in objects that should not be prefixed with 'this.'
|
|
6972
6979
|
const reserved = new Set([
|
|
6973
|
-
'event', '$ctx', '$newValue',
|
|
6980
|
+
'event', '$event', '$ctx', '$newValue',
|
|
6974
6981
|
'true', 'false', 'null', 'undefined', 'NaN', 'Infinity',
|
|
6975
6982
|
'Math', 'Date', 'String', 'Number', 'Boolean', 'Array', 'Object',
|
|
6976
6983
|
'JSON', 'console', 'window', 'document', 'navigator',
|
|
@@ -6982,7 +6989,7 @@ class ExpressionUtils {
|
|
|
6982
6989
|
// identifiers that are used (right-hand side), not assigned to (left-hand side)
|
|
6983
6990
|
let allIdentifiersInExpression;
|
|
6984
6991
|
try {
|
|
6985
|
-
allIdentifiersInExpression = ExpressionUtils.extractIdentifiers(expression, {});
|
|
6992
|
+
allIdentifiersInExpression = ExpressionUtils.extractIdentifiers(expression, {}, options);
|
|
6986
6993
|
}
|
|
6987
6994
|
catch (error) {
|
|
6988
6995
|
console.warn('[ichigo.js] Failed to extract identifiers from expression:', expression, error);
|
|
@@ -7004,7 +7011,26 @@ class ExpressionUtils {
|
|
|
7004
7011
|
try {
|
|
7005
7012
|
// Build a map of positions to replace: { start: number, end: number, name: string }[]
|
|
7006
7013
|
const replacements = [];
|
|
7007
|
-
|
|
7014
|
+
// In script mode we must not wrap in parens (that would make multi-statement input invalid).
|
|
7015
|
+
// Offsets from the parser therefore refer directly to the original expression, so no shift.
|
|
7016
|
+
const asScript = options?.asScript === true;
|
|
7017
|
+
const source = asScript ? expression : `(${expression})`;
|
|
7018
|
+
const offsetShift = asScript ? 0 : 1;
|
|
7019
|
+
const parsedAst = parse(source, { ecmaVersion: 'latest' });
|
|
7020
|
+
// Track identifiers that are locally declared within the handler body (let/const/var, function
|
|
7021
|
+
// params) so we don't rewrite them to `this.xxx`. Only relevant in script mode, where the user
|
|
7022
|
+
// can write declarations; in expression mode there are no declarations to track.
|
|
7023
|
+
const locallyDeclared = new Set();
|
|
7024
|
+
if (asScript) {
|
|
7025
|
+
full(parsedAst, (node) => {
|
|
7026
|
+
if (node.type === 'VariableDeclarator' && node.id?.type === 'Identifier') {
|
|
7027
|
+
locallyDeclared.add(node.id.name);
|
|
7028
|
+
}
|
|
7029
|
+
else if (node.type === 'FunctionDeclaration' && node.id?.type === 'Identifier') {
|
|
7030
|
+
locallyDeclared.add(node.id.name);
|
|
7031
|
+
}
|
|
7032
|
+
});
|
|
7033
|
+
}
|
|
7008
7034
|
// Collect all identifier nodes that should be replaced
|
|
7009
7035
|
// Use walk.fullAncestor to visit ALL nodes (including assignment LHS) while tracking ancestors
|
|
7010
7036
|
fullAncestor(parsedAst, (node, _state, ancestors) => {
|
|
@@ -7015,6 +7041,10 @@ class ExpressionUtils {
|
|
|
7015
7041
|
if (!bindingIdentifiers.has(node.name)) {
|
|
7016
7042
|
return;
|
|
7017
7043
|
}
|
|
7044
|
+
// Skip identifiers that were declared locally in the handler body
|
|
7045
|
+
if (locallyDeclared.has(node.name)) {
|
|
7046
|
+
return;
|
|
7047
|
+
}
|
|
7018
7048
|
// Check if this identifier is a property of a MemberExpression
|
|
7019
7049
|
// (e.g., in 'obj.prop', we should skip 'prop')
|
|
7020
7050
|
if (ancestors.length >= 1) {
|
|
@@ -7026,10 +7056,10 @@ class ExpressionUtils {
|
|
|
7026
7056
|
}
|
|
7027
7057
|
}
|
|
7028
7058
|
}
|
|
7029
|
-
// Add to replacements list (adjust for the wrapping parentheses)
|
|
7059
|
+
// Add to replacements list (adjust for the wrapping parentheses in expression mode)
|
|
7030
7060
|
replacements.push({
|
|
7031
|
-
start: node.start -
|
|
7032
|
-
end: node.end -
|
|
7061
|
+
start: node.start - offsetShift,
|
|
7062
|
+
end: node.end - offsetShift,
|
|
7033
7063
|
name: node.name
|
|
7034
7064
|
});
|
|
7035
7065
|
});
|
|
@@ -11228,10 +11258,12 @@ class VOnDirective {
|
|
|
11228
11258
|
this.#eventName = parts[0];
|
|
11229
11259
|
parts.slice(1).forEach(mod => this.#modifiers.add(mod));
|
|
11230
11260
|
}
|
|
11231
|
-
// Parse the expression to extract identifiers and create the handler wrapper
|
|
11261
|
+
// Parse the expression to extract identifiers and create the handler wrapper.
|
|
11262
|
+
// Event handlers are parsed in script mode so that users can write multi-statement bodies
|
|
11263
|
+
// (e.g. "a=1; b=2"), declarations, and control-flow constructs — matching Vue semantics.
|
|
11232
11264
|
const expression = context.attribute.value;
|
|
11233
11265
|
if (expression) {
|
|
11234
|
-
this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
|
|
11266
|
+
this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies, { asScript: true });
|
|
11235
11267
|
}
|
|
11236
11268
|
// Check if this is a lifecycle hook or a regular event
|
|
11237
11269
|
if (this.#eventName && this.#isLifecycleHook(this.#eventName)) {
|
|
@@ -11445,10 +11477,11 @@ class VOnDirective {
|
|
|
11445
11477
|
// This allows the method to access the DOM element, VNode, and userData
|
|
11446
11478
|
return originalMethod($ctx);
|
|
11447
11479
|
}
|
|
11448
|
-
// For inline
|
|
11449
|
-
// This allows assignments like "currentTab = 'shop'" to work correctly
|
|
11450
|
-
|
|
11451
|
-
const
|
|
11480
|
+
// For inline bodies, rewrite to use 'this' context
|
|
11481
|
+
// This allows assignments like "currentTab = 'shop'" to work correctly.
|
|
11482
|
+
// Script mode allows multi-statement bodies (e.g. "a=1; init()") and control-flow.
|
|
11483
|
+
const rewrittenExpr = this.#rewriteExpression(expression, identifiers, { asScript: true });
|
|
11484
|
+
const funcBody = rewrittenExpr;
|
|
11452
11485
|
const func = new Function('$ctx', funcBody);
|
|
11453
11486
|
return func.call(bindings?.raw, $ctx);
|
|
11454
11487
|
};
|
|
@@ -11478,12 +11511,15 @@ class VOnDirective {
|
|
|
11478
11511
|
// Pass event as first argument and $ctx as second argument
|
|
11479
11512
|
return originalMethod(event, $ctx);
|
|
11480
11513
|
}
|
|
11481
|
-
// For inline
|
|
11482
|
-
// This allows assignments like "currentTab = 'shop'" to work correctly
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
const
|
|
11486
|
-
|
|
11514
|
+
// For inline bodies, rewrite to use 'this' context
|
|
11515
|
+
// This allows assignments like "currentTab = 'shop'" to work correctly.
|
|
11516
|
+
// Script mode allows multi-statement bodies (e.g. "a=1; b=2") and control-flow,
|
|
11517
|
+
// so we emit the rewritten source directly as the function body (no `return (...)`).
|
|
11518
|
+
const rewrittenExpr = this.#rewriteExpression(expression, identifiers, { asScript: true });
|
|
11519
|
+
const funcBody = rewrittenExpr;
|
|
11520
|
+
// '$event' is an alias for 'event' for Vue compatibility
|
|
11521
|
+
const func = new Function('event', '$event', '$ctx', funcBody);
|
|
11522
|
+
return func.call(bindings?.raw, event, event, $ctx);
|
|
11487
11523
|
};
|
|
11488
11524
|
}
|
|
11489
11525
|
/**
|
|
@@ -11494,8 +11530,8 @@ class VOnDirective {
|
|
|
11494
11530
|
* @param identifiers The list of identifiers that are available in bindings.
|
|
11495
11531
|
* @returns The rewritten expression.
|
|
11496
11532
|
*/
|
|
11497
|
-
#rewriteExpression(expression, identifiers) {
|
|
11498
|
-
return ExpressionUtils.rewriteExpression(expression, identifiers);
|
|
11533
|
+
#rewriteExpression(expression, identifiers, options) {
|
|
11534
|
+
return ExpressionUtils.rewriteExpression(expression, identifiers, options);
|
|
11499
11535
|
}
|
|
11500
11536
|
}
|
|
11501
11537
|
|