@tsrx/core 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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Core compiler infrastructure for TSRX syntax",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.1.55",
6
+ "version": "0.1.56",
7
7
  "type": "module",
8
8
  "repository": {
9
9
  "type": "git",
package/src/plugin.js CHANGED
@@ -299,12 +299,32 @@ export function TSRXPlugin(config) {
299
299
  finishNode(node, type) {
300
300
  const finished = super.finishNode(node, type);
301
301
  if (type === 'TSModuleDeclaration') {
302
- const start = /** @type {number} */ (finished.start);
303
- const source = this.input.slice(start, start + 'namespace'.length);
304
- finished.metadata ??= { path: [] };
305
- finished.metadata.module_keyword = source.startsWith('namespace')
306
- ? 'namespace'
307
- : 'module';
302
+ const declaration = /** @type {AST.TSModuleDeclaration} */ (finished);
303
+ const start = /** @type {number} */ (declaration.start);
304
+ // acorn-typescript still exposes the legacy `global` flag without
305
+ // TSESTree's replacement `kind`; replace it at the parser boundary
306
+ // so downstream consumers only receive the current discriminator.
307
+ const legacy = /** @type {{ global?: boolean }} */ (declaration);
308
+ const prefix = this.input
309
+ .slice(start, declaration.id.start)
310
+ .replace(/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g, ' ')
311
+ .trim();
312
+ const kind =
313
+ declaration.kind ??
314
+ (legacy.global ? 'global' : prefix.endsWith('namespace') ? 'namespace' : 'module');
315
+ /** @type {AST.TSModuleDeclaration | null} */
316
+ let current = declaration;
317
+ while (current !== null) {
318
+ const current_legacy = /** @type {{ global?: boolean }} */ (current);
319
+ current.kind = kind;
320
+ delete current_legacy.global;
321
+ current.metadata ??= { path: [] };
322
+ current.metadata.module_keyword = kind;
323
+ const body = /** @type {AST.TSModuleBlock | AST.TSModuleDeclaration} */ (
324
+ /** @type {unknown} */ (current.body)
325
+ );
326
+ current = body?.type === 'TSModuleDeclaration' ? body : null;
327
+ }
308
328
  }
309
329
  return finished;
310
330
  }
package/src/scope.js CHANGED
@@ -130,7 +130,7 @@ export function create_scopes(ast, root, parent, error_options) {
130
130
  },
131
131
 
132
132
  TSModuleDeclaration(node, { state, next }) {
133
- const is_submodule = node.metadata?.module_keyword === 'module';
133
+ const is_submodule = node.declare !== true && node.kind === 'module';
134
134
  if (is_submodule && node.id?.type === 'Identifier') {
135
135
  state.scope.declare(node.id, 'normal', 'module', node);
136
136
  }
@@ -180,12 +180,18 @@ export function tsx_with_ts_locations(boundary_tokens = false, comments = undefi
180
180
  }
181
181
  },
182
182
  TSModuleDeclaration: (node, context) => {
183
- // Ambient `declare module '…' { }` must keep its `declare` — the
184
- // typeOnly/volar output is real TS and `module '…' { }` alone is a
185
- // syntax error (TS1035). Non-ambient `module name { }` blocks have no
186
- // `declare` and print unchanged.
183
+ // `declare global` is represented as a TSModuleDeclaration whose id is
184
+ // `global`; adding `module` changes it into an unrelated named module.
185
+ // Ambient `declare module '…' { }` must still keep its `declare` —
186
+ // the typeOnly/volar output is real TS and `module '…' { … }` alone is
187
+ // a syntax error (TS1035).
187
188
  if (node.declare) context.write('declare ');
188
- context.write(node.metadata?.module_keyword ?? 'module');
189
+ if (node.kind === 'global') {
190
+ context.visit(node.id);
191
+ context.visit(node.body);
192
+ return;
193
+ }
194
+ context.write(node.kind);
189
195
  context.write(' ');
190
196
  context.visit(node.id);
191
197
  context.visit(node.body);
@@ -110,7 +110,7 @@ function is_server_module_declaration(node, block_name) {
110
110
  return (
111
111
  node.type === 'TSModuleDeclaration' &&
112
112
  node.declare !== true &&
113
- node.metadata?.module_keyword === 'module' &&
113
+ node.kind === 'module' &&
114
114
  identifier_name(node.id) === block_name
115
115
  );
116
116
  }
@@ -465,6 +465,7 @@ function lower_declaration(declaration, outside_names, block_name) {
465
465
  const namespace = /** @type {AST.TSStatement<AST.TSModuleDeclaration>} */ ({
466
466
  ...declaration,
467
467
  id,
468
+ kind: 'namespace',
468
469
  metadata: { ...declaration.metadata, module_keyword: 'namespace' },
469
470
  body: { ...declaration.body, body: [...aliases, ...rest] },
470
471
  });
package/types/index.d.ts CHANGED
@@ -106,7 +106,7 @@ export interface BaseNodeMetaData {
106
106
  has_template?: boolean;
107
107
  source_name?: string;
108
108
  source_length?: number;
109
- module_keyword?: 'module' | 'namespace';
109
+ module_keyword?: 'global' | 'module' | 'namespace';
110
110
  /**
111
111
  * Generated identifier whose SOURCE span sits inside an authored string
112
112
  * literal (e.g. a server-module lowering's namespace reference carrying
@@ -1302,7 +1302,7 @@ declare module 'estree' {
1302
1302
  }
1303
1303
  interface TSModuleDeclaration extends Omit<
1304
1304
  AcornTSNode<TSESTree.TSModuleDeclaration>,
1305
- 'body' | 'id'
1305
+ 'body' | 'global' | 'id'
1306
1306
  > {
1307
1307
  body: TSModuleBlock;
1308
1308
  /** A string literal for `declare module '<specifier>'`. */