@knighted/module 1.0.0-beta.4 → 1.0.0-rc.0
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/README.md +2 -0
- package/dist/assignmentExpression.d.cts +12 -0
- package/dist/cjs/format.cjs +6 -0
- package/dist/cjs/helpers/scope.cjs +12 -0
- package/dist/cjs/scope.d.cts +6 -0
- package/dist/cjs/utils/identifiers.cjs +4 -1
- package/dist/cjs/utils/lang.cjs +3 -3
- package/dist/cjs/utils.cjs +7 -4
- package/dist/exports.d.cts +6 -0
- package/dist/expressionStatement.d.cts +4 -0
- package/dist/format.d.cts +9 -0
- package/dist/format.js +6 -0
- package/dist/formatters/assignmentExpression.d.ts +12 -0
- package/dist/formatters/expressionStatement.d.ts +4 -0
- package/dist/formatters/identifier.d.ts +12 -0
- package/dist/formatters/memberExpression.d.ts +4 -0
- package/dist/formatters/metaProperty.d.ts +4 -0
- package/dist/helpers/identifier.d.ts +31 -0
- package/dist/helpers/scope.d.ts +6 -0
- package/dist/helpers/scope.js +7 -0
- package/dist/identifier.d.cts +31 -0
- package/dist/identifiers.d.cts +19 -0
- package/dist/lang.d.cts +4 -0
- package/dist/memberExpression.d.cts +4 -0
- package/dist/metaProperty.d.cts +4 -0
- package/dist/module.d.cts +3 -0
- package/dist/parse.d.cts +2 -0
- package/dist/scope.d.cts +6 -0
- package/dist/scope.d.ts +6 -0
- package/dist/scopeNodes.d.cts +2 -0
- package/dist/src/helpers/scope.d.ts +6 -0
- package/dist/types.d.cts +44 -0
- package/dist/url.d.cts +2 -0
- package/dist/utils/identifiers.js +4 -1
- package/dist/utils/lang.js +3 -3
- package/dist/utils.d.cts +26 -0
- package/dist/utils.js +7 -4
- package/dist/walk.d.cts +20 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -133,6 +133,7 @@ Behavior notes (defaults in parentheses)
|
|
|
133
133
|
- `requireSource` (`builtin`): whether `require` comes from Node or `createRequire`.
|
|
134
134
|
- `cjsDefault` (`auto`): bundler-style default interop vs direct `module.exports`.
|
|
135
135
|
- `out`/`inPlace`: write the transformed code to a file; otherwise the function returns the transformed string only.
|
|
136
|
+
- CommonJS → ESM lowering will throw on `with` statements and unshadowed `eval` calls to avoid unsound rewrites.
|
|
136
137
|
|
|
137
138
|
See [docs/esm-to-cjs.md](docs/esm-to-cjs.md) for deeper notes on live bindings, interop helpers, top-level await behavior, and `import.meta.main` handling. For CommonJS to ESM lowering details, read [docs/cjs-to-esm.md](docs/cjs-to-esm.md).
|
|
138
139
|
|
|
@@ -141,3 +142,4 @@ See [docs/esm-to-cjs.md](docs/esm-to-cjs.md) for deeper notes on live bindings,
|
|
|
141
142
|
- Remove `@knighted/specifier` and avoid double parsing.
|
|
142
143
|
- Emit source maps and clearer diagnostics for transform choices.
|
|
143
144
|
- Broaden fixtures covering live-binding and top-level await edge cases across Node versions.
|
|
145
|
+
- Benchmark scope analysis choices: compare `periscopic`, `scope-analyzer`, and `eslint-scope` on fixtures and pick the final adapter.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, AssignmentExpression } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions, ExportsMeta } from '../types.cjs';
|
|
4
|
+
type AssignmentExpressionArg = {
|
|
5
|
+
node: AssignmentExpression;
|
|
6
|
+
parent: Node | null;
|
|
7
|
+
code: MagicString;
|
|
8
|
+
opts: FormatterOptions;
|
|
9
|
+
meta: ExportsMeta;
|
|
10
|
+
};
|
|
11
|
+
export declare const assignmentExpression: ({ node, parent: _parent, code: _code, opts, meta: _meta, }: AssignmentExpressionArg) => Promise<void>;
|
|
12
|
+
export {};
|
package/dist/cjs/format.cjs
CHANGED
|
@@ -382,6 +382,12 @@ const format = async (src, ast, opts) => {
|
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
|
+
if (shouldRaiseEsm && node.type === 'WithStatement') {
|
|
386
|
+
throw new Error('Cannot transform to ESM: with statements are not supported.');
|
|
387
|
+
}
|
|
388
|
+
if (shouldRaiseEsm && node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === 'eval' && !shadowedBindings.has('eval')) {
|
|
389
|
+
throw new Error('Cannot transform to ESM: eval is not supported.');
|
|
390
|
+
}
|
|
385
391
|
if (shouldRaiseEsm && node.type === 'CallExpression' && isRequireCall(node, shadowedBindings)) {
|
|
386
392
|
const isStatic = isStaticRequire(node, shadowedBindings);
|
|
387
393
|
const parent = ancestors[ancestors.length - 2] ?? null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.scopes = exports.scope = void 0;
|
|
7
|
+
const scopes = exports.scopes = ['BlockStatement', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression', 'ClassDeclaration', 'ClassExpression', 'ClassBody', 'StaticBlock'];
|
|
8
|
+
const scope = exports.scope = {
|
|
9
|
+
isScope(node) {
|
|
10
|
+
return scopes.includes(node.type);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
@@ -152,11 +152,14 @@ const collectModuleIdentifiers = async (ast, hoisting = true) => {
|
|
|
152
152
|
const isModuleScope = _identifier.identifier.isModuleScope(ancestors);
|
|
153
153
|
const isClassOrFuncDeclaration = _identifier.identifier.isClassOrFuncDeclarationId(ancestors);
|
|
154
154
|
const isVarDeclarationInGlobalScope = _identifier.identifier.isVarDeclarationInGlobalScope(ancestors);
|
|
155
|
+
const parent = ancestors[ancestors.length - 2];
|
|
156
|
+
const grandParent = ancestors[ancestors.length - 3];
|
|
157
|
+
const hoistSafe = parent.type === 'FunctionDeclaration' || parent.type === 'VariableDeclarator' && grandParent?.type === 'VariableDeclaration' && grandParent.kind === 'var';
|
|
155
158
|
if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
|
|
156
159
|
meta.declare.push(node);
|
|
157
160
|
|
|
158
161
|
// Check for hoisted reads
|
|
159
|
-
if (hoisting && globalReads.has(name)) {
|
|
162
|
+
if (hoisting && hoistSafe && globalReads.has(name)) {
|
|
160
163
|
const reads = globalReads.get(name);
|
|
161
164
|
if (reads) {
|
|
162
165
|
reads.forEach(read => {
|
package/dist/cjs/utils/lang.cjs
CHANGED
|
@@ -8,11 +8,11 @@ var _nodePath = require("node:path");
|
|
|
8
8
|
// Determine language from filename extension for specifier rewrite.
|
|
9
9
|
|
|
10
10
|
const getLangFromExt = filename => {
|
|
11
|
-
const ext = (0, _nodePath.extname)(filename);
|
|
12
|
-
if (ext
|
|
11
|
+
const ext = (0, _nodePath.extname)(filename).toLowerCase();
|
|
12
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
|
|
13
13
|
return 'js';
|
|
14
14
|
}
|
|
15
|
-
if (ext
|
|
15
|
+
if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
|
|
16
16
|
return 'ts';
|
|
17
17
|
}
|
|
18
18
|
if (ext === '.tsx') {
|
package/dist/cjs/utils.cjs
CHANGED
|
@@ -9,11 +9,11 @@ var _walk = require("./walk.cjs");
|
|
|
9
9
|
var _identifier = require("./helpers/identifier.cjs");
|
|
10
10
|
var _scopeNodes = require("./utils/scopeNodes.cjs");
|
|
11
11
|
const getLangFromExt = filename => {
|
|
12
|
-
const ext = (0, _nodePath.extname)(filename);
|
|
13
|
-
if (ext
|
|
12
|
+
const ext = (0, _nodePath.extname)(filename).toLowerCase();
|
|
13
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
|
|
14
14
|
return 'js';
|
|
15
15
|
}
|
|
16
|
-
if (ext
|
|
16
|
+
if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
|
|
17
17
|
return 'ts';
|
|
18
18
|
}
|
|
19
19
|
if (ext === '.tsx') {
|
|
@@ -250,11 +250,14 @@ const collectModuleIdentifiers = async (ast, hoisting = true) => {
|
|
|
250
250
|
const isModuleScope = _identifier.identifier.isModuleScope(ancestors);
|
|
251
251
|
const isClassOrFuncDeclaration = _identifier.identifier.isClassOrFuncDeclarationId(ancestors);
|
|
252
252
|
const isVarDeclarationInGlobalScope = _identifier.identifier.isVarDeclarationInGlobalScope(ancestors);
|
|
253
|
+
const parent = ancestors[ancestors.length - 2];
|
|
254
|
+
const grandParent = ancestors[ancestors.length - 3];
|
|
255
|
+
const hoistSafe = parent.type === 'FunctionDeclaration' || parent.type === 'VariableDeclarator' && grandParent?.type === 'VariableDeclaration' && grandParent.kind === 'var';
|
|
253
256
|
if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
|
|
254
257
|
meta.declare.push(node);
|
|
255
258
|
|
|
256
259
|
// Check for hoisted reads
|
|
257
|
-
if (hoisting && globalReads.has(name)) {
|
|
260
|
+
if (hoisting && hoistSafe && globalReads.has(name)) {
|
|
258
261
|
const reads = globalReads.get(name);
|
|
259
262
|
if (reads) {
|
|
260
263
|
reads.forEach(read => {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Node } from 'oxc-parser';
|
|
2
|
+
import type { CjsExport } from '../types.cjs';
|
|
3
|
+
declare const exportsRename = "__exports";
|
|
4
|
+
declare const requireMainRgx: RegExp;
|
|
5
|
+
declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
|
|
6
|
+
export { exportsRename, requireMainRgx, collectCjsExports };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, ExpressionStatement } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.cjs';
|
|
4
|
+
export declare const expressionStatement: (node: ExpressionStatement, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ParseResult } from 'oxc-parser';
|
|
2
|
+
import type { FormatterOptions } from './types.cjs';
|
|
3
|
+
/**
|
|
4
|
+
* Node added support for import.meta.main.
|
|
5
|
+
* Added in: v24.2.0, v22.18.0
|
|
6
|
+
* @see https://nodejs.org/api/esm.html#importmetamain
|
|
7
|
+
*/
|
|
8
|
+
declare const format: (src: string, ast: ParseResult, opts: FormatterOptions) => Promise<string>;
|
|
9
|
+
export { format };
|
package/dist/format.js
CHANGED
|
@@ -375,6 +375,12 @@ const format = async (src, ast, opts) => {
|
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
377
|
}
|
|
378
|
+
if (shouldRaiseEsm && node.type === 'WithStatement') {
|
|
379
|
+
throw new Error('Cannot transform to ESM: with statements are not supported.');
|
|
380
|
+
}
|
|
381
|
+
if (shouldRaiseEsm && node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === 'eval' && !shadowedBindings.has('eval')) {
|
|
382
|
+
throw new Error('Cannot transform to ESM: eval is not supported.');
|
|
383
|
+
}
|
|
378
384
|
if (shouldRaiseEsm && node.type === 'CallExpression' && isRequireCall(node, shadowedBindings)) {
|
|
379
385
|
const isStatic = isStaticRequire(node, shadowedBindings);
|
|
380
386
|
const parent = ancestors[ancestors.length - 2] ?? null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, AssignmentExpression } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions, ExportsMeta } from '../types.js';
|
|
4
|
+
type AssignmentExpressionArg = {
|
|
5
|
+
node: AssignmentExpression;
|
|
6
|
+
parent: Node | null;
|
|
7
|
+
code: MagicString;
|
|
8
|
+
opts: FormatterOptions;
|
|
9
|
+
meta: ExportsMeta;
|
|
10
|
+
};
|
|
11
|
+
export declare const assignmentExpression: ({ node, parent: _parent, code: _code, opts, meta: _meta, }: AssignmentExpressionArg) => Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, ExpressionStatement } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.js';
|
|
4
|
+
export declare const expressionStatement: (node: ExpressionStatement, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, IdentifierName } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions, ExportsMeta } from '../types.js';
|
|
4
|
+
type IdentifierArg = {
|
|
5
|
+
node: IdentifierName;
|
|
6
|
+
ancestors: Node[];
|
|
7
|
+
code: MagicString;
|
|
8
|
+
opts: FormatterOptions;
|
|
9
|
+
meta: ExportsMeta;
|
|
10
|
+
};
|
|
11
|
+
export declare const identifier: ({ node, ancestors, code, opts, meta }: IdentifierArg) => void;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { MemberExpression, Node } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.js';
|
|
4
|
+
export declare const memberExpression: (node: MemberExpression, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, MetaProperty } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.js';
|
|
4
|
+
export declare const metaProperty: (node: MetaProperty, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Node, IdentifierName } from 'oxc-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Focus exclusively on IdentifierName type as it has the name property,
|
|
4
|
+
* which is what the identifer utilities are interested in.
|
|
5
|
+
*
|
|
6
|
+
* Explicitly ignore the TSThisParameter type as it is not a valid identifier name.
|
|
7
|
+
*/
|
|
8
|
+
declare const isIdentifierName: (node: Node) => node is IdentifierName;
|
|
9
|
+
/**
|
|
10
|
+
* All methods receive the full set of ancestors, which
|
|
11
|
+
* specifically includes the node itself as the last element.
|
|
12
|
+
* The second to last element is the parent node, and so on.
|
|
13
|
+
* The first element is the root node.
|
|
14
|
+
*/
|
|
15
|
+
declare const identifier: {
|
|
16
|
+
isNamed: (node: Node) => node is IdentifierName;
|
|
17
|
+
isMetaProperty(ancestors: Node[]): boolean;
|
|
18
|
+
isModuleScope(ancestors: Node[], includeImports?: boolean): boolean;
|
|
19
|
+
isMemberExpressionRoot(ancestors: Node[]): boolean;
|
|
20
|
+
isDeclaration(ancestors: Node[]): boolean;
|
|
21
|
+
isClassOrFuncDeclarationId(ancestors: Node[]): boolean;
|
|
22
|
+
isVarDeclarationInGlobalScope(ancestors: Node[]): boolean;
|
|
23
|
+
isIife(ancestors: Node[]): boolean;
|
|
24
|
+
isFunctionExpressionId(ancestors: Node[]): boolean;
|
|
25
|
+
isExportSpecifierAlias(ancestors: Node[]): boolean;
|
|
26
|
+
isClassPropertyKey(ancestors: Node[]): boolean;
|
|
27
|
+
isMethodDefinitionKey(ancestors: Node[]): boolean;
|
|
28
|
+
isMemberKey(ancestors: Node[]): boolean;
|
|
29
|
+
isPropertyKey(ancestors: Node[]): boolean;
|
|
30
|
+
};
|
|
31
|
+
export { identifier, isIdentifierName };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const scopes = ['BlockStatement', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression', 'ClassDeclaration', 'ClassExpression', 'ClassBody', 'StaticBlock'];
|
|
2
|
+
const scope = {
|
|
3
|
+
isScope(node) {
|
|
4
|
+
return scopes.includes(node.type);
|
|
5
|
+
}
|
|
6
|
+
};
|
|
7
|
+
export { scopes, scope };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Node, IdentifierName } from 'oxc-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Focus exclusively on IdentifierName type as it has the name property,
|
|
4
|
+
* which is what the identifer utilities are interested in.
|
|
5
|
+
*
|
|
6
|
+
* Explicitly ignore the TSThisParameter type as it is not a valid identifier name.
|
|
7
|
+
*/
|
|
8
|
+
declare const isIdentifierName: (node: Node) => node is IdentifierName;
|
|
9
|
+
/**
|
|
10
|
+
* All methods receive the full set of ancestors, which
|
|
11
|
+
* specifically includes the node itself as the last element.
|
|
12
|
+
* The second to last element is the parent node, and so on.
|
|
13
|
+
* The first element is the root node.
|
|
14
|
+
*/
|
|
15
|
+
declare const identifier: {
|
|
16
|
+
isNamed: (node: Node) => node is IdentifierName;
|
|
17
|
+
isMetaProperty(ancestors: Node[]): boolean;
|
|
18
|
+
isModuleScope(ancestors: Node[], includeImports?: boolean): boolean;
|
|
19
|
+
isMemberExpressionRoot(ancestors: Node[]): boolean;
|
|
20
|
+
isDeclaration(ancestors: Node[]): boolean;
|
|
21
|
+
isClassOrFuncDeclarationId(ancestors: Node[]): boolean;
|
|
22
|
+
isVarDeclarationInGlobalScope(ancestors: Node[]): boolean;
|
|
23
|
+
isIife(ancestors: Node[]): boolean;
|
|
24
|
+
isFunctionExpressionId(ancestors: Node[]): boolean;
|
|
25
|
+
isExportSpecifierAlias(ancestors: Node[]): boolean;
|
|
26
|
+
isClassPropertyKey(ancestors: Node[]): boolean;
|
|
27
|
+
isMethodDefinitionKey(ancestors: Node[]): boolean;
|
|
28
|
+
isMemberKey(ancestors: Node[]): boolean;
|
|
29
|
+
isPropertyKey(ancestors: Node[]): boolean;
|
|
30
|
+
};
|
|
31
|
+
export { identifier, isIdentifierName };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Node } from 'oxc-parser';
|
|
2
|
+
import type { IdentMeta, Scope } from '../types.cjs';
|
|
3
|
+
declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Collects all module scope identifiers in the AST.
|
|
6
|
+
*
|
|
7
|
+
* Ignores identifiers that are in functions or classes.
|
|
8
|
+
* Ignores new scopes for StaticBlock nodes (can only reference static class members).
|
|
9
|
+
*
|
|
10
|
+
* Special case handling for these which create their own scopes,
|
|
11
|
+
* but are also valid module scope identifiers:
|
|
12
|
+
* - ClassDeclaration
|
|
13
|
+
* - FunctionDeclaration
|
|
14
|
+
*
|
|
15
|
+
* Special case handling for var inside BlockStatement
|
|
16
|
+
* which are also valid module scope identifiers.
|
|
17
|
+
*/
|
|
18
|
+
declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
|
|
19
|
+
export { collectScopeIdentifiers, collectModuleIdentifiers };
|
package/dist/lang.d.cts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { MemberExpression, Node } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.cjs';
|
|
4
|
+
export declare const memberExpression: (node: MemberExpression, parent: Node | null, src: MagicString, options: FormatterOptions, shadowed?: Set<string>) => void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
2
|
+
import type { Node, MetaProperty } from 'oxc-parser';
|
|
3
|
+
import type { FormatterOptions } from '../types.cjs';
|
|
4
|
+
export declare const metaProperty: (node: MetaProperty, parent: Node | null, src: MagicString, options: FormatterOptions) => void;
|
package/dist/parse.d.cts
ADDED
package/dist/scope.d.cts
ADDED
package/dist/scope.d.ts
ADDED
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Node, Span, IdentifierName, IdentifierReference, BindingIdentifier, LabelIdentifier, TSIndexSignatureName } from 'oxc-parser';
|
|
2
|
+
export type RewriteSpecifier = '.js' | '.mjs' | '.cjs' | '.ts' | '.mts' | '.cts' | ((value: string) => string | null | undefined);
|
|
3
|
+
export type ModuleOptions = {
|
|
4
|
+
target: 'module' | 'commonjs';
|
|
5
|
+
sourceType?: 'auto' | 'module' | 'commonjs';
|
|
6
|
+
transformSyntax?: boolean;
|
|
7
|
+
liveBindings?: 'strict' | 'loose' | 'off';
|
|
8
|
+
rewriteSpecifier?: RewriteSpecifier;
|
|
9
|
+
dirFilename?: 'inject' | 'preserve' | 'error';
|
|
10
|
+
importMeta?: 'preserve' | 'shim' | 'error';
|
|
11
|
+
importMetaMain?: 'shim' | 'warn' | 'error';
|
|
12
|
+
requireSource?: 'builtin' | 'create-require';
|
|
13
|
+
cjsDefault?: 'module-exports' | 'auto' | 'none';
|
|
14
|
+
topLevelAwait?: 'error' | 'wrap' | 'preserve';
|
|
15
|
+
out?: string;
|
|
16
|
+
inPlace?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export type SpannedNode = Node & Span;
|
|
19
|
+
export type ExportsMeta = {
|
|
20
|
+
hasExportsBeenReassigned: boolean;
|
|
21
|
+
hasDefaultExportBeenReassigned: boolean;
|
|
22
|
+
hasDefaultExportBeenAssigned: boolean;
|
|
23
|
+
defaultExportValue: unknown;
|
|
24
|
+
};
|
|
25
|
+
export type CjsExport = {
|
|
26
|
+
key: string;
|
|
27
|
+
writes: SpannedNode[];
|
|
28
|
+
fromIdentifier?: string;
|
|
29
|
+
via: Set<'exports' | 'module.exports'>;
|
|
30
|
+
reassignments: SpannedNode[];
|
|
31
|
+
hasGetter?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type IdentMeta = {
|
|
34
|
+
declare: SpannedNode[];
|
|
35
|
+
read: SpannedNode[];
|
|
36
|
+
};
|
|
37
|
+
export type Scope = {
|
|
38
|
+
type: string;
|
|
39
|
+
name: string;
|
|
40
|
+
node: Node;
|
|
41
|
+
idents: Set<string>;
|
|
42
|
+
};
|
|
43
|
+
export type FormatterOptions = Omit<ModuleOptions, 'out' | 'inPlace'>;
|
|
44
|
+
export type Identifier = IdentifierName | IdentifierReference | BindingIdentifier | LabelIdentifier | TSIndexSignatureName;
|
package/dist/url.d.cts
ADDED
|
@@ -145,11 +145,14 @@ const collectModuleIdentifiers = async (ast, hoisting = true) => {
|
|
|
145
145
|
const isModuleScope = identifier.isModuleScope(ancestors);
|
|
146
146
|
const isClassOrFuncDeclaration = identifier.isClassOrFuncDeclarationId(ancestors);
|
|
147
147
|
const isVarDeclarationInGlobalScope = identifier.isVarDeclarationInGlobalScope(ancestors);
|
|
148
|
+
const parent = ancestors[ancestors.length - 2];
|
|
149
|
+
const grandParent = ancestors[ancestors.length - 3];
|
|
150
|
+
const hoistSafe = parent.type === 'FunctionDeclaration' || parent.type === 'VariableDeclarator' && grandParent?.type === 'VariableDeclaration' && grandParent.kind === 'var';
|
|
148
151
|
if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
|
|
149
152
|
meta.declare.push(node);
|
|
150
153
|
|
|
151
154
|
// Check for hoisted reads
|
|
152
|
-
if (hoisting && globalReads.has(name)) {
|
|
155
|
+
if (hoisting && hoistSafe && globalReads.has(name)) {
|
|
153
156
|
const reads = globalReads.get(name);
|
|
154
157
|
if (reads) {
|
|
155
158
|
reads.forEach(read => {
|
package/dist/utils/lang.js
CHANGED
|
@@ -3,11 +3,11 @@ import { extname } from 'node:path';
|
|
|
3
3
|
// Determine language from filename extension for specifier rewrite.
|
|
4
4
|
|
|
5
5
|
const getLangFromExt = filename => {
|
|
6
|
-
const ext = extname(filename);
|
|
7
|
-
if (ext
|
|
6
|
+
const ext = extname(filename).toLowerCase();
|
|
7
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
|
|
8
8
|
return 'js';
|
|
9
9
|
}
|
|
10
|
-
if (ext
|
|
10
|
+
if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
|
|
11
11
|
return 'ts';
|
|
12
12
|
}
|
|
13
13
|
if (ext === '.tsx') {
|
package/dist/utils.d.cts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Node } from 'oxc-parser';
|
|
2
|
+
import type { Specifier } from '@knighted/specifier';
|
|
3
|
+
import type { IdentMeta, Scope, CjsExport } from './types.cjs';
|
|
4
|
+
type UpdateSrcLang = Parameters<Specifier['updateSrc']>[1];
|
|
5
|
+
declare const getLangFromExt: (filename: string) => UpdateSrcLang;
|
|
6
|
+
declare const isValidUrl: (url: string) => boolean;
|
|
7
|
+
declare const exportsRename = "__exports";
|
|
8
|
+
declare const requireMainRgx: RegExp;
|
|
9
|
+
declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
|
|
10
|
+
declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Collects all module scope identifiers in the AST.
|
|
13
|
+
*
|
|
14
|
+
* Ignores identifiers that are in functions or classes.
|
|
15
|
+
* Ignores new scopes for StaticBlock nodes (can only reference static class members).
|
|
16
|
+
*
|
|
17
|
+
* Special case handling for these which create their own scopes,
|
|
18
|
+
* but are also valid module scope identifiers:
|
|
19
|
+
* - ClassDeclaration
|
|
20
|
+
* - FunctionDeclaration
|
|
21
|
+
*
|
|
22
|
+
* Special case handling for var inside BlockStatement
|
|
23
|
+
* which are also valid module scope identifiers.
|
|
24
|
+
*/
|
|
25
|
+
declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
|
|
26
|
+
export { getLangFromExt, isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
|
package/dist/utils.js
CHANGED
|
@@ -3,11 +3,11 @@ import { ancestorWalk } from './walk.js';
|
|
|
3
3
|
import { identifier } from './helpers/identifier.js';
|
|
4
4
|
import { scopeNodes } from './utils/scopeNodes.js';
|
|
5
5
|
const getLangFromExt = filename => {
|
|
6
|
-
const ext = extname(filename);
|
|
7
|
-
if (ext
|
|
6
|
+
const ext = extname(filename).toLowerCase();
|
|
7
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
|
|
8
8
|
return 'js';
|
|
9
9
|
}
|
|
10
|
-
if (ext
|
|
10
|
+
if (ext === '.ts' || ext === '.mts' || ext === '.cts') {
|
|
11
11
|
return 'ts';
|
|
12
12
|
}
|
|
13
13
|
if (ext === '.tsx') {
|
|
@@ -240,11 +240,14 @@ const collectModuleIdentifiers = async (ast, hoisting = true) => {
|
|
|
240
240
|
const isModuleScope = identifier.isModuleScope(ancestors);
|
|
241
241
|
const isClassOrFuncDeclaration = identifier.isClassOrFuncDeclarationId(ancestors);
|
|
242
242
|
const isVarDeclarationInGlobalScope = identifier.isVarDeclarationInGlobalScope(ancestors);
|
|
243
|
+
const parent = ancestors[ancestors.length - 2];
|
|
244
|
+
const grandParent = ancestors[ancestors.length - 3];
|
|
245
|
+
const hoistSafe = parent.type === 'FunctionDeclaration' || parent.type === 'VariableDeclarator' && grandParent?.type === 'VariableDeclaration' && grandParent.kind === 'var';
|
|
243
246
|
if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
|
|
244
247
|
meta.declare.push(node);
|
|
245
248
|
|
|
246
249
|
// Check for hoisted reads
|
|
247
|
-
if (hoisting && globalReads.has(name)) {
|
|
250
|
+
if (hoisting && hoistSafe && globalReads.has(name)) {
|
|
248
251
|
const reads = globalReads.get(name);
|
|
249
252
|
if (reads) {
|
|
250
253
|
reads.forEach(read => {
|
package/dist/walk.d.cts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Node } from 'oxc-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Using visitorKeys instead of oxc Visitor to keep
|
|
4
|
+
* an ancestor-aware enter/leave API with this.skip()
|
|
5
|
+
* without per-node method boilerplate.
|
|
6
|
+
*/
|
|
7
|
+
type AncestorContext = {
|
|
8
|
+
skip: () => void;
|
|
9
|
+
};
|
|
10
|
+
type AncestorVisitor = {
|
|
11
|
+
enter?: (this: AncestorContext, node: Node, ancestors: Node[]) => void | Promise<void>;
|
|
12
|
+
leave?: (this: AncestorContext, node: Node, ancestors: Node[]) => void | Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
type WalkVisitor = {
|
|
15
|
+
enter?: (this: AncestorContext, node: Node, parent: Node | null) => void | Promise<void>;
|
|
16
|
+
leave?: (this: AncestorContext, node: Node, parent: Node | null) => void | Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
declare const ancestorWalk: (node: Node, visitors: AncestorVisitor) => Promise<void>;
|
|
19
|
+
declare const walk: (node: Node, visitors: WalkVisitor) => Promise<void>;
|
|
20
|
+
export { ancestorWalk, walk };
|