@tsrx/core 0.1.46 → 0.1.48

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.
@@ -1,6 +1,7 @@
1
1
  import type * as AST from 'estree';
2
+ import type * as ESTreeJSX from 'estree-jsx';
2
3
  import type { RawSourceMap } from 'source-map';
3
- import type { CompileError } from './index';
4
+ import type { CompileError, JsxHelperComponent } from './index';
4
5
 
5
6
  /**
6
7
  * Result returned by a JSX platform transform (React, Preact, Solid).
@@ -25,10 +26,8 @@ export interface JsxTransformResult {
25
26
  }
26
27
 
27
28
  /**
28
- * Shared base for the per-call transform context that the JSX factory passes
29
- * into every visitor and helper. Platform-specific transforms (e.g. Solid)
30
- * extend this with their own `needs_*` flags via `hooks.initialState`; helpers
31
- * defined in `@tsrx/core` only ever rely on these base fields.
29
+ * Per-call transform context that the JSX factory passes into every visitor
30
+ * and platform hook.
32
31
  */
33
32
  export interface JsxTransformContext {
34
33
  platform: JsxPlatform;
@@ -43,14 +42,22 @@ export interface JsxTransformContext {
43
42
  needs_dynamic_factory: boolean;
44
43
  needs_for_of_iterable: boolean;
45
44
  needs_iteration_value_type: boolean;
45
+ needs_show: boolean;
46
+ needs_for: boolean;
47
+ needs_switch: boolean;
48
+ needs_match: boolean;
49
+ needs_errored: boolean;
50
+ needs_loading: boolean;
51
+ needs_define_vapor_component: boolean;
52
+ needs_vapor_for: boolean;
46
53
  stylesheets: AST.CSS.StyleSheet[];
47
54
  type_only_style_anchors: AST.Statement[];
48
55
  module_scoped_hook_components: boolean;
49
56
  helper_state: {
50
57
  base_name: string;
51
58
  next_id: number;
52
- helpers: any[];
53
- statics: any[];
59
+ helpers: AST.Statement[];
60
+ statics: AST.Statement[];
54
61
  } | null;
55
62
  hook_helpers_enabled: boolean;
56
63
  available_bindings: Map<string, AST.Identifier>;
@@ -138,10 +145,13 @@ export interface JsxPlatformHooks {
138
145
  * child (or an expression container wrapping one).
139
146
  */
140
147
  controlFlow?: {
141
- ifStatement?: (node: any, ctx: any) => any;
142
- forOf?: (node: any, ctx: any) => any;
143
- switchStatement?: (node: any, ctx: any) => any;
144
- tryStatement?: (node: any, ctx: any) => any;
148
+ ifStatement?: (node: AST.IfStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
149
+ forOf?: (node: AST.ForOfStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
150
+ switchStatement?: (
151
+ node: AST.SwitchStatement,
152
+ ctx: JsxTransformContext,
153
+ ) => ESTreeJSX.JSXRenderNode;
154
+ tryStatement?: (node: AST.TryStatement, ctx: JsxTransformContext) => ESTreeJSX.JSXRenderNode;
145
155
  };
146
156
  /**
147
157
  * Mark a top-level call expression inside a control-flow branch as requiring
@@ -149,14 +159,19 @@ export interface JsxPlatformHooks {
149
159
  * branch instead of once per parent rerender. Vue uses this for branch-local
150
160
  * Composition API state like `ref()`.
151
161
  */
152
- isTopLevelSetupCall?: (callExpression: any, ctx: any) => boolean;
162
+ isTopLevelSetupCall?: (callExpression: AST.CallExpression, ctx: JsxTransformContext) => boolean;
153
163
  /**
154
164
  * Wrap a hoisted helper component declaration emitted by the shared control-
155
165
  * flow splitter. The default is the plain function declaration; Vue uses
156
166
  * this to wrap helpers in `defineVaporComponent(...)` so branch-local setup
157
167
  * state behaves like normal component state.
158
168
  */
159
- wrapHelperComponent?: (helperFn: any, helperId: any, ctx: any, sourceNode: any) => any;
169
+ wrapHelperComponent?: (
170
+ helperFn: AST.FunctionDeclaration,
171
+ helperId: AST.Identifier,
172
+ ctx: JsxTransformContext,
173
+ sourceNode: AST.NodeWithLocation | undefined,
174
+ ) => AST.Statement;
160
175
  /**
161
176
  * Emit hook-isolation helper components as unique module-scope declarations
162
177
  * instead of lazily creating and caching them from the parent component body.
@@ -171,27 +186,38 @@ export interface JsxPlatformHooks {
171
186
  * Solid injects `Show`, `For`, `Switch`, `Match`, `Errored`, `Loading`
172
187
  * from `solid-js`.
173
188
  */
174
- injectImports?: (program: AST.Program, ctx: any, suspenseSource: string) => void;
189
+ injectImports?: (program: AST.Program, ctx: JsxTransformContext, suspenseSource: string) => void;
175
190
  /**
176
- * Transform a Ripple element's attributes to JSX attributes. Default
177
- * is "map over `to_jsx_attribute`" plus the shared multi-`ref` merge
178
- * pass. Platforms that own a `transformElement` hook (e.g. Solid) bypass
179
- * this entirely — they never reach the dispatch path that would call
180
- * it — and run their own attribute pass inside their `transformElement`.
191
+ * Transform a Ripple element's parser-native JSX attributes. The result
192
+ * is passed through the shared multi-`ref` merge. Platforms that own a
193
+ * `transformElement` hook (e.g. Solid) run their own attribute pass inside
194
+ * that hook.
181
195
  */
182
- transformElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
196
+ transformElementAttributes?: (
197
+ attrs: ESTreeJSX.JSXAttributeNode[],
198
+ ctx: JsxTransformContext,
199
+ element: AST.TSRXJSXElement,
200
+ ) => ESTreeJSX.JSXAttributeNode[];
183
201
  /**
184
- * Rewrite or normalize raw Ripple attributes before the shared
185
- * `to_jsx_attribute()` mapping runs.
202
+ * Rewrite parser-native JSX attributes before platform transformation.
186
203
  */
187
- preprocessElementAttributes?: (attrs: any[], ctx: any, element: any) => any[];
204
+ preprocessElementAttributes?: (
205
+ attrs: ESTreeJSX.JSXAttributeNode[],
206
+ ctx: JsxTransformContext,
207
+ element: AST.TSRXJSXElement,
208
+ ) => ESTreeJSX.JSXAttributeNode[];
188
209
  /**
189
210
  * Optionally replace the default React-style `.map(...)` lowering for a
190
211
  * `for...of` body after the shared transform has already produced its render
191
212
  * statements and applied any explicit or implicit keys. Vue uses this to hand
192
213
  * the loop to the downstream Vapor JSX compiler as a typed `VaporFor` component.
193
214
  */
194
- renderForOf?: (node: any, loopParams: any[], bodyStatements: any[], ctx: any) => any | null;
215
+ renderForOf?: (
216
+ node: AST.ForOfStatement,
217
+ loopParams: AST.Pattern[],
218
+ bodyStatements: AST.Statement[],
219
+ ctx: JsxTransformContext,
220
+ ) => ESTreeJSX.JSXExpressionContainer | null;
195
221
  /**
196
222
  * Optionally replace the default React-style pending lowering for
197
223
  * `@try { ... } @pending { ... }`. The default emits
@@ -200,35 +226,35 @@ export interface JsxPlatformHooks {
200
226
  * `v-slots`.
201
227
  */
202
228
  createPendingBoundary?: (
203
- tryContent: any,
204
- fallbackContent: any,
205
- ctx: any,
206
- node: any,
207
- ) => any | null;
229
+ tryContent: ESTreeJSX.JSXRenderNode,
230
+ fallbackContent: ESTreeJSX.JSXRenderNode,
231
+ ctx: JsxTransformContext,
232
+ node: AST.TryStatement,
233
+ ) => ESTreeJSX.JSXRenderNode | null;
208
234
  /**
209
235
  * Optionally create a generated component for a catch fallback body while
210
236
  * the catch parameters are still in scope. Platforms can use this to reuse
211
237
  * one mapped catch-body component from multiple runtime catch sites.
212
238
  */
213
239
  createErrorFallbackComponent?: (
214
- catchBodyNodes: any[],
215
- catchParams: any[],
216
- ctx: any,
217
- node: any,
218
- ) => any | null;
240
+ catchBodyNodes: AST.Statement[],
241
+ catchParams: AST.Pattern[],
242
+ ctx: JsxTransformContext,
243
+ node: AST.TryStatement,
244
+ ) => JsxHelperComponent | null;
219
245
  /**
220
246
  * Optionally replace the default `try/catch` boundary wrapper. The hook
221
247
  * receives the current render content, the original try-body content before
222
248
  * any pending wrapper, and the generated catch fallback function.
223
249
  */
224
250
  createErrorBoundary?: (
225
- tryContent: any,
226
- rawTryContent: any,
227
- fallbackFn: any,
228
- ctx: any,
229
- node: any,
230
- info?: { fallbackComponent?: any },
231
- ) => any | null;
251
+ tryContent: ESTreeJSX.JSXRenderNode,
252
+ rawTryContent: ESTreeJSX.JSXRenderNode,
253
+ fallbackFn: AST.ArrowFunctionExpression,
254
+ ctx: JsxTransformContext,
255
+ node: AST.TryStatement,
256
+ info?: { fallbackComponent?: JsxHelperComponent | null },
257
+ ) => ESTreeJSX.JSXRenderNode | null;
232
258
  /**
233
259
  * Optionally move the primary `try { ... }` render content into an explicit
234
260
  * error-boundary prop instead of rendering it as the boundary's JSX children.
@@ -236,7 +262,11 @@ export interface JsxPlatformHooks {
236
262
  * zero-argument function. If a `pending` block exists, `tryContent` is the
237
263
  * already-created pending boundary so catch wrappers still enclose it.
238
264
  */
239
- createErrorBoundaryContent?: (tryContent: any, ctx: any, node: any) => any | null;
265
+ createErrorBoundaryContent?: (
266
+ tryContent: ESTreeJSX.JSXRenderNode,
267
+ ctx: JsxTransformContext,
268
+ node: AST.TryStatement,
269
+ ) => AST.Expression | null;
240
270
  /**
241
271
  * Customize lowering for a native JSX element. Default is the
242
272
  * factory's `to_jsx_element`. The hook receives the walker-transformed
@@ -245,7 +275,11 @@ export interface JsxPlatformHooks {
245
275
  * `JSXText` child it can hoist to a `textContent` attribute before the
246
276
  * generic text→JSXExpressionContainer transform runs.
247
277
  */
248
- transformElement?: (inner: any, ctx: any, rawChildren: any[]) => any;
278
+ transformElement?: (
279
+ inner: AST.TSRXJSXElement,
280
+ ctx: JsxTransformContext,
281
+ rawChildren: AST.Node[],
282
+ ) => ESTreeJSX.JSXRenderNode;
249
283
  /**
250
284
  * Optionally rewrite a host element's children into attributes or another
251
285
  * specialized child shape after generic attribute lowering but before the
@@ -258,27 +292,27 @@ export interface JsxPlatformHooks {
258
292
  * back to the default child handling.
259
293
  */
260
294
  transformElementChildren?: (
261
- element: any,
262
- walkedChildren: any[],
263
- rawChildren: any[],
264
- attrs: any[],
265
- ctx: any,
266
- ) => { children: any[]; selfClosing?: boolean } | null;
295
+ element: AST.TSRXJSXElement,
296
+ walkedChildren: AST.Node[],
297
+ rawChildren: AST.Node[],
298
+ attrs: ESTreeJSX.JSXAttributeNode[],
299
+ ctx: JsxTransformContext,
300
+ ) => { children: ESTreeJSX.JSXElement['children']; selfClosing?: boolean } | null;
267
301
  /**
268
302
  * Decide whether a JSX subtree may be hoisted to module scope when it is
269
303
  * otherwise statically safe. Targets can use this to keep runtime-sensitive
270
304
  * JSX, such as component invocations, inside render/setup execution.
271
305
  */
272
- canHoistStaticNode?: (node: any, ctx: any) => boolean;
306
+ canHoistStaticNode?: (node: ESTreeJSX.JSXElement, ctx: JsxTransformContext) => boolean;
273
307
  /**
274
308
  * Custom validation for a component body that uses top-level `await`.
275
309
  * Default: enforce `validation.requireUseServerForAwait`. Solid rejects
276
310
  * component-level await outright with a keyword-precise location.
277
311
  */
278
312
  validateComponentAwait?: (
279
- awaitNode: any,
280
- component: any,
281
- ctx: any,
313
+ awaitNode: AST.TSRXAwaitNode,
314
+ component: AST.Function,
315
+ ctx: JsxTransformContext,
282
316
  moduleUsesServerDirective: boolean,
283
317
  source: string,
284
318
  ) => void;
@@ -287,7 +321,7 @@ export interface JsxPlatformHooks {
287
321
  * initial `transform_context`. Lets solid seed its `needs_show` /
288
322
  * `needs_for` / etc. flags without forking the factory.
289
323
  */
290
- initialState?: () => Record<string, unknown>;
324
+ initialState?: () => Partial<JsxTransformContext>;
291
325
  }
292
326
 
293
327
  /**
package/types/parse.d.ts CHANGED
@@ -420,6 +420,8 @@ export namespace Parse {
420
420
  export interface AcornTypeScriptExtensions {
421
421
  tokTypes: AcornTypeScriptTokTypes;
422
422
  tokContexts: AcornTypeScriptTokContexts;
423
+ /** Whether a token type can start/continue an identifier (incl. TS soft keywords) */
424
+ tokenIsIdentifier(token: TokenType): boolean;
423
425
  }
424
426
 
425
427
  export interface AcornTypeScriptFunctionBodyConfig {
@@ -427,6 +429,31 @@ export namespace Parse {
427
429
  isClassMethod?: boolean;
428
430
  }
429
431
 
432
+ /**
433
+ * Snapshot of tokenizer state returned by `lookahead()`, mirroring
434
+ * @sveltejs/acorn-typescript's saved lookahead state. Callers inspect the
435
+ * upcoming token (`type`/`value`/`start`/`containsEsc`) without consuming it,
436
+ * and pass the snapshot to the `*WithState` contextual helpers.
437
+ */
438
+ export interface LookaheadState {
439
+ pos: number;
440
+ type: TokenType;
441
+ value: string | number | RegExp | bigint | null;
442
+ start: number;
443
+ end: number;
444
+ startLoc: AST.Position;
445
+ endLoc: AST.Position;
446
+ lastTokEnd: number;
447
+ lastTokStart: number;
448
+ lastTokStartLoc: AST.Position;
449
+ lastTokEndLoc: AST.Position;
450
+ context: TokContext[];
451
+ curLine: number;
452
+ lineStart: number;
453
+ curPosition: () => AST.Position;
454
+ containsEsc: boolean;
455
+ }
456
+
430
457
  interface Scope {
431
458
  flags: number;
432
459
  var: string[];
@@ -496,6 +523,11 @@ export namespace Parse {
496
523
  inFunction: boolean;
497
524
  /** Whether @sveltejs/acorn-typescript is currently parsing a TypeScript type */
498
525
  inType: boolean;
526
+ /**
527
+ * `value`/`type` kind of the import or export declaration currently being
528
+ * parsed (@sveltejs/acorn-typescript). `undefined` when not inside one.
529
+ */
530
+ importOrExportOuterKind?: 'value' | 'type';
499
531
  /** Stack of label names for break/continue statements */
500
532
  labels: Array<{ kind: string | null; name?: string; statementStart?: number }>;
501
533
  /** Current scope flags stack */
@@ -756,6 +788,23 @@ export namespace Parse {
756
788
  */
757
789
  expectContextual(name: string): void;
758
790
 
791
+ /**
792
+ * Like `isContextual`, but tests a `lookahead()` snapshot instead of the
793
+ * current token (@sveltejs/acorn-typescript).
794
+ * @param keyword Keyword to check (e.g. "from", "defer")
795
+ * @param state Lookahead snapshot to test
796
+ */
797
+ isContextualWithState(keyword: string, state: LookaheadState): boolean;
798
+
799
+ /**
800
+ * If `state` is the contextual keyword `name`, consume `nextCount` tokens
801
+ * and return true (@sveltejs/acorn-typescript).
802
+ * @param name Contextual keyword to eat (e.g. "type", "defer")
803
+ * @param nextCount Number of tokens to advance when it matches
804
+ * @param state Lookahead snapshot to test
805
+ */
806
+ ts_eatContextualWithState(name: string, nextCount: number, state: LookaheadState): boolean;
807
+
759
808
  /**
760
809
  * Check if semicolon can be inserted at current position (ASI)
761
810
  */
@@ -831,10 +880,11 @@ export namespace Parse {
831
880
  // Lookahead
832
881
  // ============================================================
833
882
  /**
834
- * Look ahead one token without consuming
835
- * @returns Object with type and value of next token
883
+ * Look ahead `number` tokens (default 1) without consuming, returning a
884
+ * snapshot of the tokenizer state at that position.
885
+ * @param number How many tokens to look ahead (default 1)
836
886
  */
837
- lookahead(): { type: TokenType; value: any };
887
+ lookahead(number?: number): LookaheadState;
838
888
 
839
889
  /**
840
890
  * Get next token start position
@@ -1461,7 +1511,17 @@ export namespace Parse {
1461
1511
  // Module Parsing (Import/Export)
1462
1512
  // ============================================================
1463
1513
  /** Parse import declaration */
1464
- parseImport(node: AST.Node): AST.ImportDeclaration;
1514
+ parseImport(node: AST.TSRXImportDeclaration): AST.TSRXImportDeclaration;
1515
+
1516
+ /**
1517
+ * Parse a TypeScript import-equals declaration, `import x = require('y')`
1518
+ * or `import x = A.B` (@sveltejs/acorn-typescript). Typed as
1519
+ * `ImportDeclaration` because estree has no `TSImportEqualsDeclaration`.
1520
+ */
1521
+ tsParseImportEqualsDeclaration(node: AST.Node, isExport?: boolean): AST.ImportDeclaration;
1522
+
1523
+ /** Parse an optional import-attributes clause (`with { … }` / `assert { … }`) */
1524
+ parseMaybeImportAttributes(node: AST.Node): void;
1465
1525
 
1466
1526
  /** Parse import specifiers */
1467
1527
  parseImportSpecifiers(): AST.ImportSpecifier[];