@vesk/compiler 0.2.27 → 0.2.28
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/ir-generator.d.ts.map +1 -1
- package/dist/ir-generator.js +96 -76
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAsBP,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAsBP,MAAM,uBAAuB,CAAC;AA0S/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AA07BD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAwN9E"}
|
package/dist/ir-generator.js
CHANGED
|
@@ -5,7 +5,7 @@ import { skipWhitespace, findBalancedEnd, splitTopLevel, startsWithIdentifier, s
|
|
|
5
5
|
import { stripCodeTypes } from '@vesk/compiler/src/strip-ts';
|
|
6
6
|
import { stripTypeImport } from '@vesk/compiler/src/vsk-imports';
|
|
7
7
|
import { importBindingPairs } from '@vesk/compiler/src/module-imports';
|
|
8
|
-
import {
|
|
8
|
+
import { extractImportNames, importModuleTarget } from '@vesk/compiler/src/tokens';
|
|
9
9
|
let __vskAnnotations = [];
|
|
10
10
|
/**
|
|
11
11
|
* Prop names of the component currently being processed that are declared as
|
|
@@ -168,6 +168,92 @@ function estreeCallsFetch(ast) {
|
|
|
168
168
|
}
|
|
169
169
|
return false;
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* The simple identifier a member chain *ends* in (`a.b.c` → `c`), or null when
|
|
173
|
+
* the object doesn't end in a bare name token — mirrors the tokenizer's "name
|
|
174
|
+
* two tokens before the call paren" rule so `a.b(` and `a?.b(` surface `a`,
|
|
175
|
+
* `a.b.c(` surfaces `b`, while `this.b(`, `a[0].b(` and `a(x).b(` surface
|
|
176
|
+
* nothing.
|
|
177
|
+
*/
|
|
178
|
+
function memberReceiverName(obj) {
|
|
179
|
+
if (!obj || typeof obj !== 'object')
|
|
180
|
+
return null;
|
|
181
|
+
const rec = obj;
|
|
182
|
+
if (rec.type === 'Identifier' && typeof rec.name === 'string')
|
|
183
|
+
return rec.name;
|
|
184
|
+
const prop = rec.type === 'MemberExpression' && !rec.computed ? rec.property : null;
|
|
185
|
+
if (prop && typeof prop === 'object' && prop.type === 'Identifier') {
|
|
186
|
+
const propName = prop.name;
|
|
187
|
+
if (typeof propName === 'string')
|
|
188
|
+
return propName;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Single-pass ESTree walk collecting every simple call target in `ast` —
|
|
194
|
+
* identifiers invoked directly (`fn(` / `fn<T>(`, constructor calls included)
|
|
195
|
+
* and the receiver name of a bare member call (`a.b(` → `a`, `a.b?.c(` → `b`)
|
|
196
|
+
* — plus every JSX element tag name. Mirrors the semantics of
|
|
197
|
+
* `collectCalledIdentifiers` over the equivalent text, so one walk of the
|
|
198
|
+
* already-parsed tree replaces re-tokenizing each IR raw fragment.
|
|
199
|
+
*/
|
|
200
|
+
function collectCallAndJsxTargets(ast) {
|
|
201
|
+
const targets = new Set();
|
|
202
|
+
const stack = [ast];
|
|
203
|
+
while (stack.length > 0) {
|
|
204
|
+
const candidate = stack.pop();
|
|
205
|
+
if (!candidate || typeof candidate !== 'object')
|
|
206
|
+
continue;
|
|
207
|
+
const node = candidate;
|
|
208
|
+
if (typeof node.type === 'string') {
|
|
209
|
+
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
|
210
|
+
const callee = node.callee;
|
|
211
|
+
if (callee && typeof callee === 'object') {
|
|
212
|
+
const c = callee;
|
|
213
|
+
if (c.type === 'Identifier' && typeof c.name === 'string' && node.optional !== true) {
|
|
214
|
+
targets.add(c.name);
|
|
215
|
+
}
|
|
216
|
+
else if (c.type === 'MemberExpression' && !c.computed && node.optional !== true) {
|
|
217
|
+
const receiverName = memberReceiverName(c.object);
|
|
218
|
+
if (receiverName)
|
|
219
|
+
targets.add(receiverName);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
else if (node.type === 'JSXElement') {
|
|
224
|
+
const opening = node.openingElement;
|
|
225
|
+
const tag = opening && typeof opening === 'object' ? opening.name : null;
|
|
226
|
+
if (tag && typeof tag === 'object') {
|
|
227
|
+
const t = tag;
|
|
228
|
+
if (t.type === 'JSXIdentifier' && typeof t.name === 'string') {
|
|
229
|
+
targets.add(t.name);
|
|
230
|
+
}
|
|
231
|
+
else if (t.type === 'JSXMemberExpression') {
|
|
232
|
+
const prop = t.property;
|
|
233
|
+
if (prop && typeof prop === 'object' && prop.type === 'JSXIdentifier') {
|
|
234
|
+
const propName = prop.name;
|
|
235
|
+
if (typeof propName === 'string')
|
|
236
|
+
targets.add(propName);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
for (const key of Object.keys(node)) {
|
|
242
|
+
if (key === 'parent' || key === 'loc' || key === 'start' || key === 'end' || key === 'range')
|
|
243
|
+
continue;
|
|
244
|
+
const value = node[key];
|
|
245
|
+
if (Array.isArray(value)) {
|
|
246
|
+
for (const item of value)
|
|
247
|
+
stack.push(item);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
stack.push(value);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return targets;
|
|
256
|
+
}
|
|
171
257
|
function componentUsesFetch(nodes) {
|
|
172
258
|
for (const node of nodes) {
|
|
173
259
|
if (node instanceof ServerBlock || node instanceof ClientBlock) {
|
|
@@ -1470,83 +1556,17 @@ export function generateIR(ast, source, filename) {
|
|
|
1470
1556
|
'createResource', 'getAction', 'validateActionInput', 'issuesToFieldMap', 'isFormAction',
|
|
1471
1557
|
'Show', 'For', 'Switch', 'Match',
|
|
1472
1558
|
];
|
|
1559
|
+
// One walk of the already-parsed tree finds every auto-importable call
|
|
1560
|
+
// target and JSX element name. Every IR raw the old per-fragment scan
|
|
1561
|
+
// re-tokenized ("addUsedFrom" over ~15 text slices) is a subtree of this
|
|
1562
|
+
// very same `ast` — nothing is lost, but the acorn tokenizer is invoked once
|
|
1563
|
+
// per file instead of once per fragment.
|
|
1564
|
+
const called = collectCallAndJsxTargets(ast);
|
|
1473
1565
|
const usedFunctions = new Set();
|
|
1474
|
-
const
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
if (called.has(fn))
|
|
1478
|
-
usedFunctions.add(fn);
|
|
1479
|
-
}
|
|
1480
|
-
};
|
|
1481
|
-
for (const code of topLevelCode)
|
|
1482
|
-
addUsedFrom(code);
|
|
1483
|
-
for (const code of [loadFn, staticProps]) {
|
|
1484
|
-
if (code)
|
|
1485
|
-
addUsedFrom(code);
|
|
1486
|
-
}
|
|
1487
|
-
function scanForAutoImport(nodes) {
|
|
1488
|
-
for (const node of nodes) {
|
|
1489
|
-
if (node instanceof RuntimeStatement && node.raw) {
|
|
1490
|
-
addUsedFrom(node.raw);
|
|
1491
|
-
}
|
|
1492
|
-
if (node instanceof TrackDecl && node.init) {
|
|
1493
|
-
addUsedFrom(node.init);
|
|
1494
|
-
}
|
|
1495
|
-
if (node instanceof ForLoop) {
|
|
1496
|
-
if (node.init)
|
|
1497
|
-
addUsedFrom(node.init);
|
|
1498
|
-
if (node.update)
|
|
1499
|
-
addUsedFrom(node.update);
|
|
1500
|
-
if (node.condition && node.condition.raw)
|
|
1501
|
-
addUsedFrom(node.condition.raw);
|
|
1502
|
-
scanForAutoImport(node.bodyTemplate);
|
|
1503
|
-
}
|
|
1504
|
-
if (node instanceof WhileLoop) {
|
|
1505
|
-
if (node.condition && node.condition.raw)
|
|
1506
|
-
addUsedFrom(node.condition.raw);
|
|
1507
|
-
scanForAutoImport(node.bodyTemplate);
|
|
1508
|
-
}
|
|
1509
|
-
if (node instanceof SwitchBlock) {
|
|
1510
|
-
if (node.discriminant && node.discriminant.raw)
|
|
1511
|
-
addUsedFrom(node.discriminant.raw);
|
|
1512
|
-
for (const c of node.cases) {
|
|
1513
|
-
if (c.test && c.test.raw)
|
|
1514
|
-
addUsedFrom(c.test.raw);
|
|
1515
|
-
scanForAutoImport(c.body);
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
if (node instanceof TryCatch) {
|
|
1519
|
-
scanForAutoImport(node.bodyTemplate);
|
|
1520
|
-
scanForAutoImport(node.catchBody);
|
|
1521
|
-
}
|
|
1522
|
-
if (node instanceof ComponentCall) {
|
|
1523
|
-
if (autoImportable.includes(node.componentName)) {
|
|
1524
|
-
usedFunctions.add(node.componentName);
|
|
1525
|
-
}
|
|
1526
|
-
for (const prop of node.props) {
|
|
1527
|
-
if (prop.value && prop.value.raw) {
|
|
1528
|
-
addUsedFrom(prop.value.raw);
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
scanForAutoImport(node.children);
|
|
1532
|
-
}
|
|
1533
|
-
if (node instanceof MapRegion) {
|
|
1534
|
-
scanForAutoImport(node.bodyTemplate);
|
|
1535
|
-
scanForAutoImport(node.alternateNodes);
|
|
1536
|
-
}
|
|
1537
|
-
if (node instanceof OpaqueDynamicRegion) {
|
|
1538
|
-
scanForAutoImport(node.consequentNodes);
|
|
1539
|
-
scanForAutoImport(node.alternateNodes);
|
|
1540
|
-
}
|
|
1541
|
-
if (node instanceof DynamicBinding && node.expression && node.expression.raw) {
|
|
1542
|
-
addUsedFrom(node.expression.raw);
|
|
1543
|
-
}
|
|
1544
|
-
if (node instanceof StaticNode || node instanceof ServerBlock || node instanceof ClientBlock || node instanceof HeadBlock) {
|
|
1545
|
-
scanForAutoImport(node.children);
|
|
1546
|
-
}
|
|
1547
|
-
}
|
|
1566
|
+
for (const fn of autoImportable) {
|
|
1567
|
+
if (called.has(fn))
|
|
1568
|
+
usedFunctions.add(fn);
|
|
1548
1569
|
}
|
|
1549
|
-
scanForAutoImport(components.flatMap(c => c.body));
|
|
1550
1570
|
if (usedFunctions.size > 0) {
|
|
1551
1571
|
const existing = new Set();
|
|
1552
1572
|
for (const imp of imports) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/compiler",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk compiler — lexer, parser, semantic analysis, IR, codegen",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@sveltejs/acorn-typescript": "^1.0.0",
|
|
23
|
-
"@vesk/types": "^0.2.
|
|
23
|
+
"@vesk/types": "^0.2.28",
|
|
24
24
|
"acorn": "^8.15.0",
|
|
25
25
|
"esrap": "^2.3.0",
|
|
26
26
|
"is-reference": "^3.0.0",
|