juxscript 1.1.280 → 1.1.282
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/machinery/autowrap.js +48 -99
- package/package.json +1 -1
package/machinery/autowrap.js
CHANGED
|
@@ -39,29 +39,6 @@ function containsPageStateRef(node) {
|
|
|
39
39
|
return found;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function containsJuxCall(node) {
|
|
43
|
-
let found = false;
|
|
44
|
-
walkSimple(node, {
|
|
45
|
-
CallExpression(n) { if (n.callee?.object?.name === 'jux') found = true; }
|
|
46
|
-
});
|
|
47
|
-
return found;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function getDeclaredVarNames(stmt) {
|
|
51
|
-
if (stmt.type !== 'VariableDeclaration') return [];
|
|
52
|
-
return stmt.declarations
|
|
53
|
-
.filter(d => d.id.type === 'Identifier')
|
|
54
|
-
.map(d => d.id.name);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function usesIdentifier(node, name) {
|
|
58
|
-
let found = false;
|
|
59
|
-
walkSimple(node, {
|
|
60
|
-
Identifier(n) { if (n.name === name) found = true; }
|
|
61
|
-
});
|
|
62
|
-
return found;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
42
|
function isAlreadyWrapped(stmt) {
|
|
66
43
|
return stmt.type === 'ExpressionStatement' &&
|
|
67
44
|
stmt.expression?.type === 'CallExpression' &&
|
|
@@ -69,20 +46,10 @@ function isAlreadyWrapped(stmt) {
|
|
|
69
46
|
stmt.expression?.callee?.property?.name === '__watch';
|
|
70
47
|
}
|
|
71
48
|
|
|
72
|
-
function
|
|
73
|
-
//
|
|
74
|
-
if (containsPageStateRef(stmt)) return false;
|
|
75
|
-
|
|
49
|
+
function isSetupOnly(stmt) {
|
|
50
|
+
// Statements that should stay outside __watch
|
|
76
51
|
if (stmt.type === 'ImportDeclaration') return true;
|
|
77
52
|
if (stmt.type === 'FunctionDeclaration') return true;
|
|
78
|
-
if (stmt.type === 'ExpressionStatement') {
|
|
79
|
-
const expr = stmt.expression;
|
|
80
|
-
if (expr.type === 'CallExpression' &&
|
|
81
|
-
expr.callee?.object?.name === 'jux') return true;
|
|
82
|
-
if (expr.type === 'AwaitExpression' &&
|
|
83
|
-
expr.argument?.callee?.object?.name === 'jux') return true;
|
|
84
|
-
}
|
|
85
|
-
if (stmt.type === 'VariableDeclaration') return true;
|
|
86
53
|
return false;
|
|
87
54
|
}
|
|
88
55
|
|
|
@@ -108,86 +75,68 @@ export function autowrap(source, filename = '') {
|
|
|
108
75
|
allowAwaitOutsideFunction: true,
|
|
109
76
|
});
|
|
110
77
|
} catch (err) {
|
|
111
|
-
// Can't parse — return as-is
|
|
112
78
|
return { code: source, wrappedCount: 0, details: [`parse error: ${err.message}`] };
|
|
113
79
|
}
|
|
114
80
|
|
|
115
|
-
|
|
116
|
-
let
|
|
81
|
+
// Check if there are any unwrapped pageState references at all
|
|
82
|
+
let hasUnwrappedPageState = false;
|
|
83
|
+
let firstUnwrappedIdx = -1;
|
|
84
|
+
let lastUnwrappedIdx = -1;
|
|
117
85
|
|
|
118
|
-
|
|
86
|
+
for (let i = 0; i < ast.body.length; i++) {
|
|
119
87
|
const stmt = ast.body[i];
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
if (isAlreadyWrapped(stmt)) { i++; continue; }
|
|
123
|
-
|
|
124
|
-
// VariableDeclaration reading pageState — group with subsequent stmts that use declared vars
|
|
125
|
-
if (stmt.type === 'VariableDeclaration' && containsPageStateRef(stmt)) {
|
|
126
|
-
const varNames = getDeclaredVarNames(stmt);
|
|
127
|
-
const groupStmts = [stmt];
|
|
128
|
-
let j = i + 1;
|
|
129
|
-
|
|
130
|
-
// Greedily consume following statements that use any of the declared variable names
|
|
131
|
-
while (j < ast.body.length) {
|
|
132
|
-
const next = ast.body[j];
|
|
133
|
-
if (isAlreadyWrapped(next) || isSetupStatement(next)) break;
|
|
134
|
-
if (varNames.some(v => usesIdentifier(next, v))) {
|
|
135
|
-
groupStmts.push(next);
|
|
136
|
-
j++;
|
|
137
|
-
} else {
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
needsWatch.push({
|
|
143
|
-
line: getLineNumber(source, groupStmts[0].start),
|
|
144
|
-
endLine: getLineNumber(source, groupStmts[groupStmts.length - 1].end),
|
|
145
|
-
});
|
|
146
|
-
i = j;
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Any other statement referencing pageState
|
|
88
|
+
if (isAlreadyWrapped(stmt)) continue;
|
|
89
|
+
if (isSetupOnly(stmt)) continue;
|
|
151
90
|
if (containsPageStateRef(stmt)) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
-
i++;
|
|
157
|
-
continue;
|
|
91
|
+
hasUnwrappedPageState = true;
|
|
92
|
+
if (firstUnwrappedIdx === -1) firstUnwrappedIdx = i;
|
|
93
|
+
lastUnwrappedIdx = i;
|
|
158
94
|
}
|
|
159
|
-
|
|
160
|
-
i++;
|
|
161
95
|
}
|
|
162
96
|
|
|
163
|
-
if (
|
|
97
|
+
if (!hasUnwrappedPageState) {
|
|
164
98
|
return { code: source, wrappedCount: 0, details: [] };
|
|
165
99
|
}
|
|
166
100
|
|
|
167
|
-
//
|
|
101
|
+
// Find the contiguous range: from first unwrapped pageState ref
|
|
102
|
+
// to end of file (or last unwrapped ref), including any non-pageState
|
|
103
|
+
// statements in between (they may depend on reactive variables).
|
|
104
|
+
// But exclude leading setup-only statements (imports, function decls).
|
|
105
|
+
|
|
106
|
+
// Walk backwards from firstUnwrappedIdx to include any immediately
|
|
107
|
+
// preceding non-setup statements that declare variables used later
|
|
108
|
+
let rangeStart = firstUnwrappedIdx;
|
|
109
|
+
let rangeEnd = lastUnwrappedIdx;
|
|
110
|
+
|
|
111
|
+
// Collect all statements in the range
|
|
168
112
|
const lines = source.split('\n');
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const blockLines = lines.slice(startIdx, endIdx + 1);
|
|
176
|
-
const indent = blockLines[0].match(/^(\s*)/)[1];
|
|
177
|
-
|
|
178
|
-
const wrapped = [
|
|
179
|
-
`${indent}pageState.__watch(() => {`,
|
|
180
|
-
...blockLines.map(l => `${indent} ${l.trim()}`),
|
|
181
|
-
`${indent}});`,
|
|
182
|
-
];
|
|
183
|
-
|
|
184
|
-
lines.splice(startIdx, endIdx - startIdx + 1, ...wrapped);
|
|
185
|
-
details.push(`L${item.line}-${item.endLine}`);
|
|
113
|
+
const stmtsInRange = ast.body.slice(rangeStart, rangeEnd + 1);
|
|
114
|
+
|
|
115
|
+
// Check if ALL pageState refs are already wrapped (nothing to do)
|
|
116
|
+
const unwrappedInRange = stmtsInRange.filter(s => !isAlreadyWrapped(s) && containsPageStateRef(s));
|
|
117
|
+
if (unwrappedInRange.length === 0) {
|
|
118
|
+
return { code: source, wrappedCount: 0, details: [] };
|
|
186
119
|
}
|
|
187
120
|
|
|
121
|
+
const startLine = getLineNumber(source, stmtsInRange[0].start);
|
|
122
|
+
const endLine = getLineNumber(source, stmtsInRange[stmtsInRange.length - 1].end);
|
|
123
|
+
|
|
124
|
+
const startIdx = startLine - 1;
|
|
125
|
+
const endIdx = endLine - 1;
|
|
126
|
+
const blockLines = lines.slice(startIdx, endIdx + 1);
|
|
127
|
+
const indent = blockLines[0].match(/^(\s*)/)[1];
|
|
128
|
+
|
|
129
|
+
const wrapped = [
|
|
130
|
+
`${indent}pageState.__watch(() => {`,
|
|
131
|
+
...blockLines.map(l => `${indent} ${l.trimEnd()}`),
|
|
132
|
+
`${indent}});`,
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
lines.splice(startIdx, endIdx - startIdx + 1, ...wrapped);
|
|
136
|
+
|
|
188
137
|
return {
|
|
189
138
|
code: lines.join('\n'),
|
|
190
|
-
wrappedCount:
|
|
191
|
-
details
|
|
139
|
+
wrappedCount: 1,
|
|
140
|
+
details: [`L${startLine}-${endLine} (single watch block)`],
|
|
192
141
|
};
|
|
193
142
|
}
|