@tsrx/core 0.1.49 → 0.1.51
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/package.json +10 -1
- package/src/analyze/prune.js +62 -77
- package/src/analyze/validation.js +7 -7
- package/src/parse/index.js +59 -80
- package/src/plugin.js +219 -107
- package/src/runtime/language-helpers.js +34 -25
- package/src/runtime/ref.js +57 -36
- package/src/scope.js +4 -5
- package/src/source-map-utils.js +8 -22
- package/src/transform/imports.js +8 -14
- package/src/transform/jsx/ast-builders.js +4 -1
- package/src/transform/jsx/index.js +1 -13
- package/src/transform/jsx/server-module.js +102 -96
- package/src/transform/jsx-hoist.js +4 -4
- package/src/transform/lazy.js +196 -137
- package/src/transform/scoping.js +108 -100
- package/src/transform/segments.js +24 -49
- package/src/transform/style-ref.js +92 -106
- package/src/transform/stylesheet.js +5 -21
- package/src/utils/ast.js +25 -20
- package/src/utils/builders.js +66 -2
- package/src/vite/dep-scan.js +135 -0
- package/types/index.d.ts +317 -17
- package/types/parse.d.ts +98 -13
- package/types/runtime/language-helpers.d.ts +10 -5
- package/types/runtime/ref.d.ts +63 -14
- package/types/vite/dep-scan.d.ts +26 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @import * as AST from 'estree' */
|
|
2
|
-
/** @import { JsxPlatform } from '@tsrx/core/types' */
|
|
2
|
+
/** @import { JsxPlatform, MaybeLocated } from '@tsrx/core/types' */
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Type-only lowering of a platform's `module <name> { … }` server-module
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
*/
|
|
79
79
|
|
|
80
80
|
import * as b from '../../utils/builders.js';
|
|
81
|
+
import { is_ast_node } from '../../utils/ast.js';
|
|
81
82
|
|
|
82
83
|
const HOISTED_IMPORT_PREFIX = '__tsrx_server_import$';
|
|
83
84
|
|
|
@@ -101,12 +102,13 @@ const WALK_SKIP_KEYS = new Set([
|
|
|
101
102
|
* them verbatim (where TS flags them) mirrors the build failure instead of
|
|
102
103
|
* hiding it.
|
|
103
104
|
*
|
|
104
|
-
* @param {
|
|
105
|
+
* @param {AST.Node} node
|
|
105
106
|
* @param {string} block_name
|
|
107
|
+
* @returns {node is AST.TSModuleDeclaration}
|
|
106
108
|
*/
|
|
107
109
|
function is_server_module_declaration(node, block_name) {
|
|
108
110
|
return (
|
|
109
|
-
node
|
|
111
|
+
node.type === 'TSModuleDeclaration' &&
|
|
110
112
|
node.declare !== true &&
|
|
111
113
|
node.metadata?.module_keyword === 'module' &&
|
|
112
114
|
identifier_name(node.id) === block_name
|
|
@@ -114,7 +116,7 @@ function is_server_module_declaration(node, block_name) {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/**
|
|
117
|
-
* @param {
|
|
119
|
+
* @param {AST.Node | null | undefined} node
|
|
118
120
|
* @returns {string | null}
|
|
119
121
|
*/
|
|
120
122
|
function identifier_name(node) {
|
|
@@ -124,18 +126,25 @@ function identifier_name(node) {
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
/**
|
|
127
|
-
* @param {
|
|
129
|
+
* @param {AST.Node} node
|
|
128
130
|
* @param {string} import_specifier
|
|
131
|
+
* @returns {node is AST.ImportDeclaration}
|
|
129
132
|
*/
|
|
130
133
|
function is_server_import(node, import_specifier) {
|
|
131
|
-
return
|
|
134
|
+
return (
|
|
135
|
+
node.type === 'ImportDeclaration' &&
|
|
136
|
+
node.source.type === 'Literal' &&
|
|
137
|
+
node.source.value === import_specifier
|
|
138
|
+
);
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
/**
|
|
135
142
|
* Copy `node`'s authored location onto a replacement node.
|
|
136
|
-
*
|
|
137
|
-
* @
|
|
138
|
-
* @
|
|
143
|
+
*
|
|
144
|
+
* @template {AST.Node} T
|
|
145
|
+
* @param {T} node
|
|
146
|
+
* @param {MaybeLocated | null | undefined} source
|
|
147
|
+
* @returns {T}
|
|
139
148
|
*/
|
|
140
149
|
function with_location(node, source) {
|
|
141
150
|
if (source?.start != null) node.start = source.start;
|
|
@@ -161,15 +170,15 @@ function with_location(node, source) {
|
|
|
161
170
|
* from the wrong length.
|
|
162
171
|
*
|
|
163
172
|
* @param {string} name
|
|
164
|
-
* @param {
|
|
173
|
+
* @param {MaybeLocated} literal
|
|
165
174
|
* @returns {AST.Identifier}
|
|
166
175
|
*/
|
|
167
176
|
function string_span_namespace_ref(name, literal) {
|
|
168
177
|
const node = b.id(name);
|
|
169
178
|
node.metadata.string_literal_source_span = true;
|
|
170
179
|
if (
|
|
171
|
-
typeof literal
|
|
172
|
-
typeof literal
|
|
180
|
+
typeof literal.start === 'number' &&
|
|
181
|
+
typeof literal.end === 'number' &&
|
|
173
182
|
literal.end - literal.start >= 2
|
|
174
183
|
) {
|
|
175
184
|
node.start = literal.start + 1;
|
|
@@ -198,31 +207,32 @@ function string_span_namespace_ref(name, literal) {
|
|
|
198
207
|
* the name as a conflict costs nothing but an alias, and keeps the lowering
|
|
199
208
|
* from ever changing what the client half of the file typechecks against.
|
|
200
209
|
*
|
|
201
|
-
* @param {
|
|
202
|
-
* @param {
|
|
210
|
+
* @param {AST.Program} ast
|
|
211
|
+
* @param {AST.Node} declaration
|
|
203
212
|
* @returns {Set<string>}
|
|
204
213
|
*/
|
|
205
214
|
function collect_outside_identifier_names(ast, declaration) {
|
|
206
215
|
/** @type {Set<string>} */
|
|
207
216
|
const names = new Set();
|
|
217
|
+
/** @type {WeakSet<object>} */
|
|
208
218
|
const seen = new WeakSet();
|
|
209
|
-
/** @param {
|
|
210
|
-
function walk(
|
|
211
|
-
if (
|
|
219
|
+
/** @param {unknown} value */
|
|
220
|
+
function walk(value) {
|
|
221
|
+
if (value === null || typeof value !== 'object' || seen.has(value) || value === declaration) {
|
|
212
222
|
return;
|
|
213
223
|
}
|
|
214
|
-
seen.add(
|
|
215
|
-
if (Array.isArray(
|
|
216
|
-
for (const child of
|
|
224
|
+
seen.add(value);
|
|
225
|
+
if (Array.isArray(value)) {
|
|
226
|
+
for (const child of value) walk(child);
|
|
217
227
|
return;
|
|
218
228
|
}
|
|
219
|
-
if (
|
|
220
|
-
if (
|
|
221
|
-
names.add(
|
|
229
|
+
if (!is_ast_node(value)) return;
|
|
230
|
+
if (value.type === 'Identifier' || value.type === 'JSXIdentifier') {
|
|
231
|
+
names.add(value.name);
|
|
222
232
|
}
|
|
223
|
-
for (const [key,
|
|
233
|
+
for (const [key, child] of Object.entries(value)) {
|
|
224
234
|
if (WALK_SKIP_KEYS.has(key)) continue;
|
|
225
|
-
if (
|
|
235
|
+
if (child !== null && typeof child === 'object') walk(child);
|
|
226
236
|
}
|
|
227
237
|
}
|
|
228
238
|
walk(ast);
|
|
@@ -235,27 +245,25 @@ function collect_outside_identifier_names(ast, declaration) {
|
|
|
235
245
|
* locations so hover / rename still target the source. `make_init`
|
|
236
246
|
* builds a fresh init expression per call (nodes are never shared).
|
|
237
247
|
*
|
|
238
|
-
* @param {
|
|
248
|
+
* @param {AST.ImportSpecifier[]} specifiers
|
|
239
249
|
* @param {() => AST.Expression} make_init
|
|
240
|
-
* @param {
|
|
250
|
+
* @param {MaybeLocated} loc_node
|
|
251
|
+
* @returns {AST.VariableDeclaration}
|
|
241
252
|
*/
|
|
242
253
|
function build_destructure(specifiers, make_init, loc_node) {
|
|
243
254
|
const pattern = with_location(
|
|
244
255
|
b.object_pattern(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
specifier.imported?.type === 'Identifier' &&
|
|
254
|
-
specifier.imported.name === specifier.local?.name,
|
|
255
|
-
),
|
|
256
|
-
specifier,
|
|
256
|
+
specifiers.map((specifier) =>
|
|
257
|
+
with_location(
|
|
258
|
+
b.assignment_prop(
|
|
259
|
+
{ ...specifier.imported },
|
|
260
|
+
{ ...specifier.local },
|
|
261
|
+
false,
|
|
262
|
+
specifier.imported.type === 'Identifier' &&
|
|
263
|
+
specifier.imported.name === specifier.local.name,
|
|
257
264
|
),
|
|
258
|
-
|
|
265
|
+
specifier,
|
|
266
|
+
),
|
|
259
267
|
),
|
|
260
268
|
),
|
|
261
269
|
loc_node,
|
|
@@ -264,40 +272,24 @@ function build_destructure(specifiers, make_init, loc_node) {
|
|
|
264
272
|
return with_location(b.declaration('const', [declarator]), loc_node);
|
|
265
273
|
}
|
|
266
274
|
|
|
267
|
-
/**
|
|
268
|
-
* `<left>.<right>` qualified name. Callers pass a `right` that carries the
|
|
269
|
-
* authored specifier span, so hover / rename on the imported name resolve.
|
|
270
|
-
*
|
|
271
|
-
* @param {AST.Identifier} left
|
|
272
|
-
* @param {any} right
|
|
273
|
-
*/
|
|
274
|
-
function qualified_name(left, right) {
|
|
275
|
-
return {
|
|
276
|
-
type: 'TSQualifiedName',
|
|
277
|
-
left,
|
|
278
|
-
right,
|
|
279
|
-
metadata: { path: [] },
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
|
|
283
275
|
/**
|
|
284
276
|
* `type <local> = <left>.<right>;` for a type-only import specifier.
|
|
285
|
-
*
|
|
277
|
+
* Callers pass the specifier's imported name as `right`; a DEFAULT import
|
|
286
278
|
* passes `default` (which has no authored span of its own).
|
|
287
279
|
*
|
|
288
|
-
*
|
|
280
|
+
* `right` carries the authored specifier span, so hover / rename on the
|
|
281
|
+
* imported name resolve.
|
|
282
|
+
*
|
|
283
|
+
* @param {AST.ImportSpecifier | AST.ImportDefaultSpecifier} specifier
|
|
289
284
|
* @param {() => AST.Identifier} make_left
|
|
290
|
-
* @param {
|
|
285
|
+
* @param {AST.Identifier} right
|
|
286
|
+
* @returns {AST.TSStatement<AST.TSTypeAliasDeclaration>}
|
|
291
287
|
*/
|
|
292
|
-
function build_type_alias(specifier, make_left, right
|
|
288
|
+
function build_type_alias(specifier, make_left, right) {
|
|
293
289
|
return with_location(
|
|
294
290
|
b.ts_type_alias(
|
|
295
291
|
{ ...specifier.local },
|
|
296
|
-
|
|
297
|
-
type: 'TSTypeReference',
|
|
298
|
-
typeName: qualified_name(make_left(), right),
|
|
299
|
-
metadata: { path: [] },
|
|
300
|
-
}),
|
|
292
|
+
b.ts_type_reference(b.ts_qualified_name(make_left(), right)),
|
|
301
293
|
),
|
|
302
294
|
specifier,
|
|
303
295
|
);
|
|
@@ -309,20 +301,12 @@ function build_type_alias(specifier, make_left, right = { ...specifier.imported
|
|
|
309
301
|
* binding, where a `const` keeps only the value and a `type` alias only
|
|
310
302
|
* the type.
|
|
311
303
|
*
|
|
312
|
-
* @param {
|
|
313
|
-
* @param {
|
|
304
|
+
* @param {AST.ImportDeclaration['specifiers'][number]} specifier
|
|
305
|
+
* @param {AST.EntityName} module_reference
|
|
306
|
+
* @returns {AST.TSStatement<AST.TSImportEqualsDeclaration>}
|
|
314
307
|
*/
|
|
315
308
|
function build_import_equals(specifier, module_reference) {
|
|
316
|
-
return with_location(
|
|
317
|
-
/** @type {any} */ ({
|
|
318
|
-
type: 'TSImportEqualsDeclaration',
|
|
319
|
-
id: { ...specifier.local },
|
|
320
|
-
moduleReference: module_reference,
|
|
321
|
-
importKind: 'value',
|
|
322
|
-
metadata: { path: [] },
|
|
323
|
-
}),
|
|
324
|
-
specifier,
|
|
325
|
-
);
|
|
309
|
+
return with_location(b.ts_import_equals({ ...specifier.local }, module_reference), specifier);
|
|
326
310
|
}
|
|
327
311
|
|
|
328
312
|
/**
|
|
@@ -341,17 +325,22 @@ function build_import_equals(specifier, module_reference) {
|
|
|
341
325
|
* `<ns>.default` is not (a JSON module's namespace has no `default`
|
|
342
326
|
* member under bundler resolution).
|
|
343
327
|
*
|
|
344
|
-
* @param {
|
|
328
|
+
* @param {AST.ImportDeclaration} statement
|
|
345
329
|
* @param {string} hoisted_name
|
|
330
|
+
* @returns {{ hoisted: AST.ImportDeclaration, aliases: AST.Node[] }}
|
|
346
331
|
*/
|
|
347
332
|
function lower_colliding_import(statement, hoisted_name) {
|
|
348
333
|
const default_name = hoisted_name + '_default';
|
|
334
|
+
/** @type {AST.Node[]} */
|
|
349
335
|
const aliases = [];
|
|
336
|
+
/** @type {AST.ImportSpecifier[]} */
|
|
350
337
|
const destructured_specifiers = [];
|
|
351
338
|
let needs_default_hoist = false;
|
|
352
339
|
let needs_namespace_hoist = false;
|
|
353
340
|
for (const specifier of statement.specifiers) {
|
|
354
|
-
const type_only =
|
|
341
|
+
const type_only =
|
|
342
|
+
statement.importKind === 'type' ||
|
|
343
|
+
(specifier.type === 'ImportSpecifier' && specifier.importKind === 'type');
|
|
355
344
|
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
356
345
|
needs_namespace_hoist = true;
|
|
357
346
|
aliases.push(build_import_equals(specifier, b.id(hoisted_name)));
|
|
@@ -367,7 +356,7 @@ function lower_colliding_import(statement, hoisted_name) {
|
|
|
367
356
|
);
|
|
368
357
|
aliases.push(with_location(b.declaration('const', [declarator]), specifier));
|
|
369
358
|
}
|
|
370
|
-
} else if (specifier.imported
|
|
359
|
+
} else if (specifier.imported.type !== 'Identifier') {
|
|
371
360
|
// String-named — neither an entity name nor a qualified type
|
|
372
361
|
// reference can hold a string, so type-only ones land here too:
|
|
373
362
|
// the destructure is the one PARSEABLE fallback, at the cost of
|
|
@@ -376,13 +365,15 @@ function lower_colliding_import(statement, hoisted_name) {
|
|
|
376
365
|
destructured_specifiers.push(specifier);
|
|
377
366
|
} else if (type_only) {
|
|
378
367
|
needs_namespace_hoist = true;
|
|
379
|
-
aliases.push(
|
|
368
|
+
aliases.push(
|
|
369
|
+
build_type_alias(specifier, () => b.id(hoisted_name), { ...specifier.imported }),
|
|
370
|
+
);
|
|
380
371
|
} else {
|
|
381
372
|
needs_namespace_hoist = true;
|
|
382
373
|
aliases.push(
|
|
383
374
|
build_import_equals(
|
|
384
375
|
specifier,
|
|
385
|
-
|
|
376
|
+
b.ts_qualified_name(b.id(hoisted_name), { ...specifier.imported }),
|
|
386
377
|
),
|
|
387
378
|
);
|
|
388
379
|
}
|
|
@@ -393,6 +384,7 @@ function lower_colliding_import(statement, hoisted_name) {
|
|
|
393
384
|
|
|
394
385
|
// Only the specifiers the aliases reference — an unreferenced mangled
|
|
395
386
|
// specifier would draw a spurious `noUnusedLocals` diagnostic.
|
|
387
|
+
/** @type {AST.ImportDeclaration['specifiers']} */
|
|
396
388
|
const hoist_specifiers = [];
|
|
397
389
|
if (needs_default_hoist) {
|
|
398
390
|
hoist_specifiers.push({
|
|
@@ -415,6 +407,7 @@ function lower_colliding_import(statement, hoisted_name) {
|
|
|
415
407
|
source: with_location({ ...statement.source }, statement.source),
|
|
416
408
|
importKind: 'value',
|
|
417
409
|
attributes: statement.attributes,
|
|
410
|
+
metadata: { path: [] },
|
|
418
411
|
},
|
|
419
412
|
statement,
|
|
420
413
|
);
|
|
@@ -425,13 +418,17 @@ function lower_colliding_import(statement, hoisted_name) {
|
|
|
425
418
|
* Replace the server block with hoisted imports plus a namespace-valued
|
|
426
419
|
* binding the checker can see through.
|
|
427
420
|
*
|
|
428
|
-
* @param {
|
|
421
|
+
* @param {AST.TSModuleDeclaration} declaration
|
|
429
422
|
* @param {Set<string>} outside_names
|
|
430
423
|
* @param {string} block_name
|
|
424
|
+
* @returns {AST.Node[]}
|
|
431
425
|
*/
|
|
432
426
|
function lower_declaration(declaration, outside_names, block_name) {
|
|
427
|
+
/** @type {AST.Node[]} */
|
|
433
428
|
const hoisted_imports = [];
|
|
429
|
+
/** @type {AST.Node[]} */
|
|
434
430
|
const aliases = [];
|
|
431
|
+
/** @type {AST.Node[]} */
|
|
435
432
|
const rest = [];
|
|
436
433
|
let hoisted_index = 0;
|
|
437
434
|
|
|
@@ -440,8 +437,8 @@ function lower_declaration(declaration, outside_names, block_name) {
|
|
|
440
437
|
rest.push(statement);
|
|
441
438
|
continue;
|
|
442
439
|
}
|
|
443
|
-
const collides =
|
|
444
|
-
outside_names.has(specifier.local
|
|
440
|
+
const collides = statement.specifiers.some((specifier) =>
|
|
441
|
+
outside_names.has(specifier.local.name),
|
|
445
442
|
);
|
|
446
443
|
if (!collides) {
|
|
447
444
|
// Authored node, hoisted as-is — its locations map 1:1.
|
|
@@ -462,15 +459,15 @@ function lower_declaration(declaration, outside_names, block_name) {
|
|
|
462
459
|
// Identifier (the authored id could be a string Literal, whose span then
|
|
463
460
|
// gets the same string-literal mapping treatment as the import source).
|
|
464
461
|
const id =
|
|
465
|
-
declaration.id
|
|
462
|
+
declaration.id.type === 'Literal'
|
|
466
463
|
? string_span_namespace_ref(block_name, declaration.id)
|
|
467
464
|
: with_location(b.id(block_name), declaration.id);
|
|
468
|
-
const namespace = {
|
|
465
|
+
const namespace = /** @type {AST.TSStatement<AST.TSModuleDeclaration>} */ ({
|
|
469
466
|
...declaration,
|
|
470
467
|
id,
|
|
471
468
|
metadata: { ...declaration.metadata, module_keyword: 'namespace' },
|
|
472
469
|
body: { ...declaration.body, body: [...aliases, ...rest] },
|
|
473
|
-
};
|
|
470
|
+
});
|
|
474
471
|
return [...hoisted_imports, namespace];
|
|
475
472
|
}
|
|
476
473
|
|
|
@@ -488,13 +485,14 @@ function lower_declaration(declaration, outside_names, block_name) {
|
|
|
488
485
|
* imports) are a hard compile error in the dialect — those statements
|
|
489
486
|
* stay verbatim so the editor's TS2307 mirrors the build error.
|
|
490
487
|
*
|
|
491
|
-
* @param {
|
|
488
|
+
* @param {AST.ImportDeclaration} statement
|
|
492
489
|
* @param {string} block_name
|
|
490
|
+
* @returns {AST.Node[]}
|
|
493
491
|
*/
|
|
494
492
|
function lower_server_import(statement, block_name) {
|
|
495
|
-
const specifiers = statement.specifiers
|
|
493
|
+
const specifiers = statement.specifiers;
|
|
496
494
|
if (specifiers.length === 0) return [];
|
|
497
|
-
if (specifiers.
|
|
495
|
+
if (!specifiers.every((specifier) => specifier.type === 'ImportSpecifier')) {
|
|
498
496
|
return [statement];
|
|
499
497
|
}
|
|
500
498
|
|
|
@@ -502,18 +500,23 @@ function lower_server_import(statement, block_name) {
|
|
|
502
500
|
// inner span, so hover / go-to-def on the module name resolves to the
|
|
503
501
|
// lowered block while the literal keeps its string coloring.
|
|
504
502
|
const namespace_ref = () => string_span_namespace_ref(block_name, statement.source);
|
|
503
|
+
/** @type {AST.Node[]} */
|
|
505
504
|
const lowered = [];
|
|
505
|
+
/** @type {AST.ImportSpecifier[]} */
|
|
506
506
|
const destructured_specifiers = [];
|
|
507
507
|
for (const specifier of specifiers) {
|
|
508
|
-
if (specifier.imported
|
|
508
|
+
if (specifier.imported.type !== 'Identifier') {
|
|
509
509
|
// String-named — inexpressible in an entity name or qualified type
|
|
510
510
|
// reference alike, so type-only ones fall back here too.
|
|
511
511
|
destructured_specifiers.push(specifier);
|
|
512
512
|
} else if (statement.importKind === 'type' || specifier.importKind === 'type') {
|
|
513
|
-
lowered.push(build_type_alias(specifier, namespace_ref));
|
|
513
|
+
lowered.push(build_type_alias(specifier, namespace_ref, { ...specifier.imported }));
|
|
514
514
|
} else {
|
|
515
515
|
lowered.push(
|
|
516
|
-
build_import_equals(
|
|
516
|
+
build_import_equals(
|
|
517
|
+
specifier,
|
|
518
|
+
b.ts_qualified_name(namespace_ref(), { ...specifier.imported }),
|
|
519
|
+
),
|
|
517
520
|
);
|
|
518
521
|
}
|
|
519
522
|
}
|
|
@@ -540,7 +543,9 @@ function lower_server_import(statement, block_name) {
|
|
|
540
543
|
*/
|
|
541
544
|
export function lower_server_module_for_types(ast, server_module) {
|
|
542
545
|
const { blockName: block_name, importSpecifier: import_specifier } = server_module;
|
|
543
|
-
|
|
546
|
+
// estree's `Statement` union has no TS declarations in it, so the module
|
|
547
|
+
// body is scanned as plain nodes and re-typed on the way back out.
|
|
548
|
+
const body = /** @type {AST.Node[]} */ (ast?.body);
|
|
544
549
|
if (!Array.isArray(body)) return ast;
|
|
545
550
|
const declaration = body.find((node) => is_server_module_declaration(node, block_name));
|
|
546
551
|
// A body-less `module server;` only occurs mid-edit / in loose parses;
|
|
@@ -551,6 +556,7 @@ export function lower_server_module_for_types(ast, server_module) {
|
|
|
551
556
|
// The lowered namespace claims the authored block name at module scope; a
|
|
552
557
|
// block import local with the same name must be aliased out of its way.
|
|
553
558
|
outside_names.add(block_name);
|
|
559
|
+
/** @type {AST.Node[]} */
|
|
554
560
|
const new_body = [];
|
|
555
561
|
for (const statement of body) {
|
|
556
562
|
if (statement === declaration) {
|
|
@@ -561,5 +567,5 @@ export function lower_server_module_for_types(ast, server_module) {
|
|
|
561
567
|
new_body.push(statement);
|
|
562
568
|
}
|
|
563
569
|
}
|
|
564
|
-
return { ...ast, body: new_body };
|
|
570
|
+
return { ...ast, body: /** @type {AST.Program['body']} */ (new_body) };
|
|
565
571
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {AST.Literal} node
|
|
14
14
|
* @returns {boolean}
|
|
15
15
|
*/
|
|
16
16
|
export function is_static_literal(node) {
|
|
@@ -24,7 +24,7 @@ export function is_static_literal(node) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* @param {
|
|
27
|
+
* @param {AST.Node | null | undefined} node
|
|
28
28
|
* @returns {boolean}
|
|
29
29
|
*/
|
|
30
30
|
export function is_hoist_safe_expression(node) {
|
|
@@ -60,7 +60,7 @@ export function is_hoist_safe_expression(node) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* @param {
|
|
63
|
+
* @param {AST.Node | null | undefined} node
|
|
64
64
|
* @returns {boolean}
|
|
65
65
|
*/
|
|
66
66
|
export function is_hoist_safe_jsx_child(node) {
|
|
@@ -115,7 +115,7 @@ export function is_hoist_safe_jsx_node(node) {
|
|
|
115
115
|
|
|
116
116
|
// Lowered dynamic tags reference a component-scoped const and resolve at
|
|
117
117
|
// runtime — never static, never hoistable.
|
|
118
|
-
if (
|
|
118
|
+
if (node.metadata?.dynamicElement === true) {
|
|
119
119
|
return false;
|
|
120
120
|
}
|
|
121
121
|
|