@knighted/module 1.1.0 → 1.2.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 -7
- package/dist/ast.d.ts +39 -0
- package/dist/cjs/ast.d.cts +39 -0
- package/dist/cjs/exports.d.cts +4 -1
- package/dist/cjs/format.cjs +43 -25
- package/dist/cjs/formatters/assignmentExpression.cjs +1 -1
- package/dist/cjs/formatters/identifier.cjs +2 -2
- package/dist/cjs/formatters/memberExpression.cjs +1 -1
- package/dist/cjs/helpers/ast.cjs +29 -0
- package/dist/cjs/helpers/identifier.cjs +5 -3
- package/dist/cjs/module.cjs +8 -6
- package/dist/cjs/specifier.cjs +1 -1
- package/dist/cjs/types.d.cts +2 -0
- package/dist/cjs/utils/exports.cjs +1 -1
- package/dist/cjs/utils/identifiers.cjs +2 -2
- package/dist/exports.d.ts +4 -1
- package/dist/format.js +43 -25
- package/dist/formatters/assignmentExpression.js +1 -1
- package/dist/formatters/identifier.js +2 -2
- package/dist/formatters/memberExpression.js +1 -1
- package/dist/helpers/ast.d.ts +39 -0
- package/dist/helpers/ast.js +18 -0
- package/dist/helpers/identifier.js +5 -4
- package/dist/module.js +9 -7
- package/dist/specifier.js +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/{src/utils → utils}/exports.d.ts +4 -1
- package/dist/utils/exports.js +1 -1
- package/dist/utils/identifiers.js +2 -2
- package/package.json +10 -13
- package/dist/cjs/utils.cjs +0 -274
- package/dist/cjs/utils.d.cts +0 -23
- package/dist/src/format.d.ts +0 -9
- package/dist/src/module.d.ts +0 -3
- package/dist/src/parse.d.ts +0 -2
- package/dist/src/specifier.d.ts +0 -16
- package/dist/src/types.d.ts +0 -93
- package/dist/src/utils.d.ts +0 -23
- package/dist/src/walk.d.ts +0 -20
- package/dist/utils.d.ts +0 -23
- package/dist/utils.js +0 -265
- /package/dist/{src/formatters → formatters}/assignmentExpression.d.ts +0 -0
- /package/dist/{src/formatters → formatters}/expressionStatement.d.ts +0 -0
- /package/dist/{src/formatters → formatters}/identifier.d.ts +0 -0
- /package/dist/{src/formatters → formatters}/memberExpression.d.ts +0 -0
- /package/dist/{src/formatters → formatters}/metaProperty.d.ts +0 -0
- /package/dist/{src/helpers → helpers}/identifier.d.ts +0 -0
- /package/dist/{src/utils → utils}/identifiers.d.ts +0 -0
- /package/dist/{src/utils → utils}/lang.d.ts +0 -0
- /package/dist/{src/utils → utils}/scopeNodes.d.ts +0 -0
- /package/dist/{src/utils → utils}/url.d.ts +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Node } from 'oxc-parser';
|
|
2
|
+
import type { CjsExport } from '../types.js';
|
|
3
|
+
export type IdentifierNode = Extract<Node, {
|
|
4
|
+
type: 'Identifier';
|
|
5
|
+
}>;
|
|
6
|
+
export type LiteralNode = Extract<Node, {
|
|
7
|
+
type: 'Literal';
|
|
8
|
+
value?: unknown;
|
|
9
|
+
}>;
|
|
10
|
+
export type MemberExpressionNode = Extract<Node, {
|
|
11
|
+
type: 'MemberExpression';
|
|
12
|
+
}>;
|
|
13
|
+
export type CallExpressionNode = Extract<Node, {
|
|
14
|
+
type: 'CallExpression';
|
|
15
|
+
}>;
|
|
16
|
+
export type ProgramNode = Extract<Node, {
|
|
17
|
+
type: 'Program';
|
|
18
|
+
body: Node[];
|
|
19
|
+
}>;
|
|
20
|
+
export type ModuleExportNameNode = Extract<Node, {
|
|
21
|
+
type: 'Identifier' | 'Literal';
|
|
22
|
+
}>;
|
|
23
|
+
export type ImportDefaultSpecifierNode = Extract<Node, {
|
|
24
|
+
type: 'ImportDefaultSpecifier';
|
|
25
|
+
}>;
|
|
26
|
+
export type ImportNamespaceSpecifierNode = Extract<Node, {
|
|
27
|
+
type: 'ImportNamespaceSpecifier';
|
|
28
|
+
}>;
|
|
29
|
+
export type ImportSpecifierNode = Extract<Node, {
|
|
30
|
+
type: 'ImportSpecifier';
|
|
31
|
+
}>;
|
|
32
|
+
export type ExportsMap = Map<string, CjsExport> & {
|
|
33
|
+
hasUnsupportedExportWrite?: boolean;
|
|
34
|
+
};
|
|
35
|
+
export declare const isAstNode: (value: unknown) => value is Node;
|
|
36
|
+
export declare const isIdentifierNode: (node: Node | null | undefined) => node is IdentifierNode;
|
|
37
|
+
export declare const isMemberExpressionNode: (node: Node | null | undefined) => node is MemberExpressionNode;
|
|
38
|
+
export declare const isCallExpressionNode: (node: Node | null | undefined) => node is CallExpressionNode;
|
|
39
|
+
export declare const getModuleExportName: (name: ModuleExportNameNode | null | undefined) => string | null;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const isAstNode = value => {
|
|
2
|
+
return Boolean(value) && typeof value === 'object' && 'type' in value;
|
|
3
|
+
};
|
|
4
|
+
export const isIdentifierNode = node => {
|
|
5
|
+
return node?.type === 'Identifier';
|
|
6
|
+
};
|
|
7
|
+
export const isMemberExpressionNode = node => {
|
|
8
|
+
return node?.type === 'MemberExpression';
|
|
9
|
+
};
|
|
10
|
+
export const isCallExpressionNode = node => {
|
|
11
|
+
return node?.type === 'CallExpression';
|
|
12
|
+
};
|
|
13
|
+
export const getModuleExportName = name => {
|
|
14
|
+
if (!name) return null;
|
|
15
|
+
if (name.type === 'Identifier') return name.name;
|
|
16
|
+
if (name.type === 'Literal' && typeof name.value === 'string') return name.value;
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { analyze } from 'periscopic';
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* Focus exclusively on IdentifierName type as it has the name property,
|
|
5
4
|
* which is what the identifer utilities are interested in.
|
|
@@ -121,14 +120,16 @@ const identifier = {
|
|
|
121
120
|
const node = ancestors[ancestors.length - 1];
|
|
122
121
|
const varBoundScopes = ['ClassDeclaration', 'ClassExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'];
|
|
123
122
|
const declaratorIndex = ancestors.findIndex(ancestor => {
|
|
124
|
-
|
|
123
|
+
if (ancestor.type !== 'VariableDeclarator') return false;
|
|
124
|
+
return ancestor === node || isInBindingPattern(ancestor.id, node);
|
|
125
125
|
});
|
|
126
126
|
if (declaratorIndex === -1) return false;
|
|
127
|
-
const
|
|
127
|
+
const declaratorNode = ancestors[declaratorIndex];
|
|
128
128
|
const declaration = ancestors[declaratorIndex - 1];
|
|
129
|
+
if (declaratorNode?.type !== 'VariableDeclarator') return false;
|
|
129
130
|
return declaration?.type === 'VariableDeclaration' && declaration.kind === 'var' && ancestors.every(ancestor => {
|
|
130
131
|
return !varBoundScopes.includes(ancestor.type);
|
|
131
|
-
}) && (
|
|
132
|
+
}) && (declaratorNode.id === node || isInBindingPattern(declaratorNode.id, node));
|
|
132
133
|
},
|
|
133
134
|
isIife(ancestors) {
|
|
134
135
|
const parent = ancestors[ancestors.length - 2];
|
package/dist/module.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { specifier } from './specifier.js';
|
|
4
|
-
import { parse } from '
|
|
5
|
-
import { format } from '
|
|
6
|
-
import { getLangFromExt } from '
|
|
4
|
+
import { parse } from './parse.js';
|
|
5
|
+
import { format } from './format.js';
|
|
6
|
+
import { getLangFromExt } from './utils/lang.js';
|
|
7
7
|
import { builtinModules } from 'node:module';
|
|
8
8
|
import { resolve as pathResolve, dirname as pathDirname, extname, join } from 'node:path';
|
|
9
9
|
import { readFile as fsReadFile, stat } from 'node:fs/promises';
|
|
10
|
-
import { parse as parseModule } from '
|
|
11
|
-
import { walk } from '
|
|
10
|
+
import { parse as parseModule } from './parse.js';
|
|
11
|
+
import { walk } from './walk.js';
|
|
12
12
|
const collapseSpecifier = value => value.replace(/['"`+)\s]|new String\(/g, '');
|
|
13
13
|
const builtinSpecifiers = new Set(builtinModules.map(mod => mod.startsWith('node:') ? mod.slice(5) : mod).flatMap(mod => {
|
|
14
14
|
const parts = mod.split('/');
|
|
@@ -160,6 +160,7 @@ const defaultOptions = {
|
|
|
160
160
|
idiomaticExports: 'safe',
|
|
161
161
|
importMetaPrelude: 'auto',
|
|
162
162
|
topLevelAwait: 'error',
|
|
163
|
+
cwd: undefined,
|
|
163
164
|
out: undefined,
|
|
164
165
|
inPlace: false
|
|
165
166
|
};
|
|
@@ -169,10 +170,11 @@ const transform = async (filename, options = defaultOptions) => {
|
|
|
169
170
|
...options,
|
|
170
171
|
filePath: filename
|
|
171
172
|
};
|
|
173
|
+
const cwdBase = opts.cwd ? resolve(opts.cwd) : process.cwd();
|
|
172
174
|
const appendMode = options?.appendJsExtension ?? (opts.target === 'module' ? 'relative-only' : 'off');
|
|
173
175
|
const dirIndex = opts.appendDirectoryIndex === undefined ? 'index.js' : opts.appendDirectoryIndex;
|
|
174
176
|
const detectCycles = opts.detectCircularRequires ?? 'off';
|
|
175
|
-
const file = resolve(filename);
|
|
177
|
+
const file = resolve(cwdBase, filename);
|
|
176
178
|
const code = (await readFile(file)).toString();
|
|
177
179
|
const ast = parse(filename, code);
|
|
178
180
|
let source = await format(code, ast, opts);
|
|
@@ -189,7 +191,7 @@ const transform = async (filename, options = defaultOptions) => {
|
|
|
189
191
|
if (detectCycles !== 'off' && opts.target === 'module' && opts.transformSyntax) {
|
|
190
192
|
await detectCircularRequireGraph(file, detectCycles, dirIndex || 'index.js');
|
|
191
193
|
}
|
|
192
|
-
const outputPath = opts.inPlace ? file : opts.out ? resolve(opts.out) : undefined;
|
|
194
|
+
const outputPath = opts.inPlace ? file : opts.out ? resolve(cwdBase, opts.out) : undefined;
|
|
193
195
|
if (outputPath) {
|
|
194
196
|
await writeFile(outputPath, source);
|
|
195
197
|
}
|
package/dist/specifier.js
CHANGED
|
@@ -2,7 +2,7 @@ import { resolve } from 'node:path';
|
|
|
2
2
|
import { stat, readFile } from 'node:fs/promises';
|
|
3
3
|
import MagicString from 'magic-string';
|
|
4
4
|
import { parseSync } from 'oxc-parser';
|
|
5
|
-
import { walk } from '
|
|
5
|
+
import { walk } from './walk.js';
|
|
6
6
|
const isStringLiteral = node => {
|
|
7
7
|
return node.type === 'Literal' && typeof node.value === 'string';
|
|
8
8
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export type ModuleOptions = {
|
|
|
48
48
|
diagnostics?: (diag: Diagnostic) => void;
|
|
49
49
|
/** Optional source file path used for diagnostics context. */
|
|
50
50
|
filePath?: string;
|
|
51
|
+
/** Base directory used to resolve relative `out` paths; defaults to process.cwd(). */
|
|
52
|
+
cwd?: string;
|
|
51
53
|
/** Output directory or file path when writing. */
|
|
52
54
|
out?: string;
|
|
53
55
|
/** Overwrite input files instead of writing to out. */
|
|
@@ -2,5 +2,8 @@ import type { Node } from 'oxc-parser';
|
|
|
2
2
|
import type { CjsExport } from '../types.js';
|
|
3
3
|
declare const exportsRename = "__exports";
|
|
4
4
|
declare const requireMainRgx: RegExp;
|
|
5
|
-
|
|
5
|
+
type ExportsMap = Map<string, CjsExport> & {
|
|
6
|
+
hasUnsupportedExportWrite?: boolean;
|
|
7
|
+
};
|
|
8
|
+
declare const collectCjsExports: (ast: Node) => Promise<ExportsMap>;
|
|
6
9
|
export { exportsRename, requireMainRgx, collectCjsExports };
|
package/dist/utils/exports.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ancestorWalk } from '
|
|
2
|
-
import { identifier } from '
|
|
1
|
+
import { ancestorWalk } from '../walk.js';
|
|
2
|
+
import { identifier } from '../helpers/identifier.js';
|
|
3
3
|
import { scopeNodes } from './scopeNodes.js';
|
|
4
4
|
const addBindingNames = (pattern, into) => {
|
|
5
5
|
if (!pattern) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knighted/module",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Bidirectional transform for ES modules and CommonJS.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/module.js",
|
|
@@ -18,14 +18,6 @@
|
|
|
18
18
|
},
|
|
19
19
|
"./package.json": "./package.json"
|
|
20
20
|
},
|
|
21
|
-
"imports": {
|
|
22
|
-
"#parse": "./src/parse.js",
|
|
23
|
-
"#format": "./src/format.js",
|
|
24
|
-
"#utils/*.js": "./src/utils/*.js",
|
|
25
|
-
"#walk": "./src/walk.js",
|
|
26
|
-
"#helpers/*.js": "./src/helpers/*.js",
|
|
27
|
-
"#formatters/*.js": "./src/formatters/*.js"
|
|
28
|
-
},
|
|
29
21
|
"engines": {
|
|
30
22
|
"node": ">=22.21.1 <23 || >=24 <25"
|
|
31
23
|
},
|
|
@@ -35,13 +27,13 @@
|
|
|
35
27
|
"prettier": "prettier -w .",
|
|
36
28
|
"prettier:check": "prettier -c .",
|
|
37
29
|
"lint": "oxlint --config oxlint.json .",
|
|
38
|
-
"prepare": "husky
|
|
30
|
+
"prepare": "husky",
|
|
39
31
|
"test": "c8 --reporter=text --reporter=text-summary --reporter=lcov tsx --test --test-reporter=spec test/*.ts",
|
|
40
32
|
"build:types": "tsc --emitDeclarationOnly",
|
|
41
33
|
"build:dual": "babel-dual-package src --extensions .ts",
|
|
42
34
|
"build": "npm run build:types && npm run build:dual",
|
|
43
|
-
"
|
|
44
|
-
"
|
|
35
|
+
"cycles": "madge --circular src --extensions ts,js --ts-config tsconfig.json",
|
|
36
|
+
"prepack": "npm run build"
|
|
45
37
|
},
|
|
46
38
|
"keywords": [
|
|
47
39
|
"esm",
|
|
@@ -72,6 +64,7 @@
|
|
|
72
64
|
"c8": "^10.1.3",
|
|
73
65
|
"husky": "^9.1.7",
|
|
74
66
|
"lint-staged": "^16.2.7",
|
|
67
|
+
"madge": "^8.0.0",
|
|
75
68
|
"oxlint": "^1.35.0",
|
|
76
69
|
"prettier": "^3.7.4",
|
|
77
70
|
"tsx": "^4.21.0",
|
|
@@ -79,10 +72,14 @@
|
|
|
79
72
|
},
|
|
80
73
|
"dependencies": {
|
|
81
74
|
"magic-string": "^0.30.21",
|
|
82
|
-
"node-module-type": "^1.0.4",
|
|
83
75
|
"oxc-parser": "^0.105.0",
|
|
84
76
|
"periscopic": "^4.0.2"
|
|
85
77
|
},
|
|
78
|
+
"overrides": {
|
|
79
|
+
"module-lookup-amd": {
|
|
80
|
+
"glob": "^9.0.0"
|
|
81
|
+
}
|
|
82
|
+
},
|
|
86
83
|
"prettier": {
|
|
87
84
|
"arrowParens": "avoid",
|
|
88
85
|
"printWidth": 90,
|
package/dist/cjs/utils.cjs
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.requireMainRgx = exports.isValidUrl = exports.exportsRename = exports.collectScopeIdentifiers = exports.collectModuleIdentifiers = exports.collectCjsExports = void 0;
|
|
7
|
-
var _walk = require("./walk.cjs");
|
|
8
|
-
var _identifier = require("./helpers/identifier.cjs");
|
|
9
|
-
var _scopeNodes = require("./utils/scopeNodes.cjs");
|
|
10
|
-
const isValidUrl = url => {
|
|
11
|
-
try {
|
|
12
|
-
new URL(url);
|
|
13
|
-
return true;
|
|
14
|
-
} catch {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
exports.isValidUrl = isValidUrl;
|
|
19
|
-
const exportsRename = exports.exportsRename = '__exports';
|
|
20
|
-
const requireMainRgx = exports.requireMainRgx = /(require\.main\s*===\s*module|module\s*===\s*require\.main)/g;
|
|
21
|
-
const resolveExportTarget = node => {
|
|
22
|
-
if (node.type !== 'MemberExpression') return null;
|
|
23
|
-
const base = node.object;
|
|
24
|
-
const prop = node.property;
|
|
25
|
-
if (prop.type !== 'Identifier') return null;
|
|
26
|
-
if (base.type === 'Identifier' && base.name === 'exports') {
|
|
27
|
-
return {
|
|
28
|
-
key: prop.name,
|
|
29
|
-
via: 'exports'
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
if (base.type === 'MemberExpression' && base.object.type === 'Identifier' && base.object.name === 'module' && base.property.type === 'Identifier' && base.property.name === 'exports') {
|
|
33
|
-
return {
|
|
34
|
-
key: prop.name,
|
|
35
|
-
via: 'module.exports'
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
if (base.type === 'Identifier' && base.name === 'module' && prop.type === 'Identifier' && prop.name === 'exports') {
|
|
39
|
-
return {
|
|
40
|
-
key: 'default',
|
|
41
|
-
via: 'module.exports'
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
return null;
|
|
45
|
-
};
|
|
46
|
-
const collectCjsExports = async ast => {
|
|
47
|
-
const exportsMap = new Map();
|
|
48
|
-
const localToExport = new Map();
|
|
49
|
-
await (0, _walk.ancestorWalk)(ast, {
|
|
50
|
-
enter(node) {
|
|
51
|
-
if (node.type === 'AssignmentExpression') {
|
|
52
|
-
const target = resolveExportTarget(node.left);
|
|
53
|
-
if (target) {
|
|
54
|
-
const entry = exportsMap.get(target.key) ?? {
|
|
55
|
-
key: target.key,
|
|
56
|
-
writes: [],
|
|
57
|
-
via: new Set(),
|
|
58
|
-
reassignments: []
|
|
59
|
-
};
|
|
60
|
-
entry.via.add(target.via);
|
|
61
|
-
entry.writes.push(node);
|
|
62
|
-
if (node.right.type === 'Identifier') {
|
|
63
|
-
entry.fromIdentifier ??= node.right.name;
|
|
64
|
-
if (entry.fromIdentifier) {
|
|
65
|
-
const set = localToExport.get(entry.fromIdentifier) ?? new Set();
|
|
66
|
-
set.add(target.key);
|
|
67
|
-
localToExport.set(entry.fromIdentifier, set);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
exportsMap.set(target.key, entry);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (node.left.type === 'Identifier') {
|
|
74
|
-
const keys = localToExport.get(node.left.name);
|
|
75
|
-
if (keys) {
|
|
76
|
-
keys.forEach(key => {
|
|
77
|
-
const entry = exportsMap.get(key);
|
|
78
|
-
if (entry) {
|
|
79
|
-
entry.reassignments.push(node);
|
|
80
|
-
exportsMap.set(key, entry);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
return exportsMap;
|
|
89
|
-
};
|
|
90
|
-
exports.collectCjsExports = collectCjsExports;
|
|
91
|
-
const collectScopeIdentifiers = (node, scopes) => {
|
|
92
|
-
const {
|
|
93
|
-
type
|
|
94
|
-
} = node;
|
|
95
|
-
switch (type) {
|
|
96
|
-
case 'BlockStatement':
|
|
97
|
-
case 'ClassBody':
|
|
98
|
-
scopes.push({
|
|
99
|
-
node,
|
|
100
|
-
type: 'Block',
|
|
101
|
-
name: type,
|
|
102
|
-
idents: new Set()
|
|
103
|
-
});
|
|
104
|
-
break;
|
|
105
|
-
case 'FunctionDeclaration':
|
|
106
|
-
case 'FunctionExpression':
|
|
107
|
-
case 'ArrowFunctionExpression':
|
|
108
|
-
{
|
|
109
|
-
const name = node.id ? node.id.name : 'anonymous';
|
|
110
|
-
const scope = {
|
|
111
|
-
node,
|
|
112
|
-
name,
|
|
113
|
-
type: 'Function',
|
|
114
|
-
idents: new Set()
|
|
115
|
-
};
|
|
116
|
-
node.params.map(param => {
|
|
117
|
-
if (param.type === 'TSParameterProperty') {
|
|
118
|
-
return param.parameter;
|
|
119
|
-
}
|
|
120
|
-
if (param.type === 'RestElement') {
|
|
121
|
-
return param.argument;
|
|
122
|
-
}
|
|
123
|
-
if (param.type === 'AssignmentPattern') {
|
|
124
|
-
return param.left;
|
|
125
|
-
}
|
|
126
|
-
return param;
|
|
127
|
-
}).filter(_identifier.identifier.isNamed).forEach(param => {
|
|
128
|
-
scope.idents.add(param.name);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* If a FunctionExpression has an id, it is a named function expression.
|
|
133
|
-
* The function expression name shadows the module scope identifier, so
|
|
134
|
-
* we don't want to count reads of module identifers that have the same name.
|
|
135
|
-
* They also do not cause a SyntaxError if the function expression name is
|
|
136
|
-
* the same as a module scope identifier.
|
|
137
|
-
*
|
|
138
|
-
* TODO: Is this necessary for FunctionDeclaration?
|
|
139
|
-
*/
|
|
140
|
-
if (node.type === 'FunctionExpression' && node.id) {
|
|
141
|
-
scope.idents.add(node.id.name);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// First add the function to any previous scopes
|
|
145
|
-
if (scopes.length > 0) {
|
|
146
|
-
scopes[scopes.length - 1].idents.add(name);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Then add the function scope to the scopes stack
|
|
150
|
-
scopes.push(scope);
|
|
151
|
-
}
|
|
152
|
-
break;
|
|
153
|
-
case 'ClassDeclaration':
|
|
154
|
-
{
|
|
155
|
-
const className = node.id ? node.id.name : 'anonymous';
|
|
156
|
-
|
|
157
|
-
// First add the class to any previous scopes
|
|
158
|
-
if (scopes.length > 0) {
|
|
159
|
-
scopes[scopes.length - 1].idents.add(className);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Then add the class to the scopes stack
|
|
163
|
-
scopes.push({
|
|
164
|
-
node,
|
|
165
|
-
name: className,
|
|
166
|
-
type: 'Class',
|
|
167
|
-
idents: new Set()
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
break;
|
|
171
|
-
case 'ClassExpression':
|
|
172
|
-
{}
|
|
173
|
-
break;
|
|
174
|
-
case 'VariableDeclaration':
|
|
175
|
-
if (scopes.length > 0) {
|
|
176
|
-
const scope = scopes[scopes.length - 1];
|
|
177
|
-
node.declarations.forEach(decl => {
|
|
178
|
-
if (decl.type === 'VariableDeclarator' && decl.id.type === 'Identifier') {
|
|
179
|
-
scope.idents.add(decl.id.name);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
break;
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Collects all module scope identifiers in the AST.
|
|
189
|
-
*
|
|
190
|
-
* Ignores identifiers that are in functions or classes.
|
|
191
|
-
* Ignores new scopes for StaticBlock nodes (can only reference static class members).
|
|
192
|
-
*
|
|
193
|
-
* Special case handling for these which create their own scopes,
|
|
194
|
-
* but are also valid module scope identifiers:
|
|
195
|
-
* - ClassDeclaration
|
|
196
|
-
* - FunctionDeclaration
|
|
197
|
-
*
|
|
198
|
-
* Special case handling for var inside BlockStatement
|
|
199
|
-
* which are also valid module scope identifiers.
|
|
200
|
-
*/
|
|
201
|
-
exports.collectScopeIdentifiers = collectScopeIdentifiers;
|
|
202
|
-
const collectModuleIdentifiers = async (ast, hoisting = true) => {
|
|
203
|
-
const identifiers = new Map();
|
|
204
|
-
const globalReads = new Map();
|
|
205
|
-
const scopes = [];
|
|
206
|
-
await (0, _walk.ancestorWalk)(ast, {
|
|
207
|
-
enter(node, ancestors) {
|
|
208
|
-
const {
|
|
209
|
-
type
|
|
210
|
-
} = node;
|
|
211
|
-
collectScopeIdentifiers(node, scopes);
|
|
212
|
-
|
|
213
|
-
// Add module scope identifiers to the registry map
|
|
214
|
-
|
|
215
|
-
if (type === 'Identifier') {
|
|
216
|
-
const {
|
|
217
|
-
name
|
|
218
|
-
} = node;
|
|
219
|
-
const meta = identifiers.get(name) ?? {
|
|
220
|
-
declare: [],
|
|
221
|
-
read: []
|
|
222
|
-
};
|
|
223
|
-
const isDeclaration = _identifier.identifier.isDeclaration(ancestors);
|
|
224
|
-
const inScope = scopes.some(scope => scope.idents.has(name) || scope.name === name);
|
|
225
|
-
if (hoisting && !_identifier.identifier.isDeclaration(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors) && !_identifier.identifier.isIife(ancestors) && !inScope) {
|
|
226
|
-
if (globalReads.has(name)) {
|
|
227
|
-
globalReads.get(name)?.push(node);
|
|
228
|
-
} else {
|
|
229
|
-
globalReads.set(name, [node]);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (isDeclaration) {
|
|
233
|
-
const isModuleScope = _identifier.identifier.isModuleScope(ancestors);
|
|
234
|
-
const isClassOrFuncDeclaration = _identifier.identifier.isClassOrFuncDeclarationId(ancestors);
|
|
235
|
-
const isVarDeclarationInGlobalScope = _identifier.identifier.isVarDeclarationInGlobalScope(ancestors);
|
|
236
|
-
const parent = ancestors[ancestors.length - 2];
|
|
237
|
-
const grandParent = ancestors[ancestors.length - 3];
|
|
238
|
-
const hoistSafe = parent.type === 'FunctionDeclaration' || parent.type === 'VariableDeclarator' && grandParent?.type === 'VariableDeclaration' && grandParent.kind === 'var';
|
|
239
|
-
if (isModuleScope || isClassOrFuncDeclaration || isVarDeclarationInGlobalScope) {
|
|
240
|
-
meta.declare.push(node);
|
|
241
|
-
|
|
242
|
-
// Check for hoisted reads
|
|
243
|
-
if (hoisting && hoistSafe && globalReads.has(name)) {
|
|
244
|
-
const reads = globalReads.get(name);
|
|
245
|
-
if (reads) {
|
|
246
|
-
reads.forEach(read => {
|
|
247
|
-
if (!meta.read.includes(read)) {
|
|
248
|
-
meta.read.push(read);
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
identifiers.set(name, meta);
|
|
254
|
-
}
|
|
255
|
-
} else {
|
|
256
|
-
if (identifiers.has(name) && !inScope && !_identifier.identifier.isIife(ancestors) && !_identifier.identifier.isFunctionExpressionId(ancestors) && !_identifier.identifier.isExportSpecifierAlias(ancestors) && !_identifier.identifier.isClassPropertyKey(ancestors) && !_identifier.identifier.isMethodDefinitionKey(ancestors) && !_identifier.identifier.isMemberKey(ancestors) && !_identifier.identifier.isPropertyKey(ancestors)) {
|
|
257
|
-
// Closure is referencing module scope identifier
|
|
258
|
-
meta.read.push(node);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
leave(node) {
|
|
264
|
-
const {
|
|
265
|
-
type
|
|
266
|
-
} = node;
|
|
267
|
-
if (_scopeNodes.scopeNodes.includes(type)) {
|
|
268
|
-
scopes.pop();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
return identifiers;
|
|
273
|
-
};
|
|
274
|
-
exports.collectModuleIdentifiers = collectModuleIdentifiers;
|
package/dist/cjs/utils.d.cts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { Node } from 'oxc-parser';
|
|
2
|
-
import type { IdentMeta, Scope, CjsExport } from './types.cjs';
|
|
3
|
-
declare const isValidUrl: (url: string) => boolean;
|
|
4
|
-
declare const exportsRename = "__exports";
|
|
5
|
-
declare const requireMainRgx: RegExp;
|
|
6
|
-
declare const collectCjsExports: (ast: Node) => Promise<Map<string, CjsExport>>;
|
|
7
|
-
declare const collectScopeIdentifiers: (node: Node, scopes: Scope[]) => void;
|
|
8
|
-
/**
|
|
9
|
-
* Collects all module scope identifiers in the AST.
|
|
10
|
-
*
|
|
11
|
-
* Ignores identifiers that are in functions or classes.
|
|
12
|
-
* Ignores new scopes for StaticBlock nodes (can only reference static class members).
|
|
13
|
-
*
|
|
14
|
-
* Special case handling for these which create their own scopes,
|
|
15
|
-
* but are also valid module scope identifiers:
|
|
16
|
-
* - ClassDeclaration
|
|
17
|
-
* - FunctionDeclaration
|
|
18
|
-
*
|
|
19
|
-
* Special case handling for var inside BlockStatement
|
|
20
|
-
* which are also valid module scope identifiers.
|
|
21
|
-
*/
|
|
22
|
-
declare const collectModuleIdentifiers: (ast: Node, hoisting?: boolean) => Promise<Map<string, IdentMeta>>;
|
|
23
|
-
export { isValidUrl, collectScopeIdentifiers, collectModuleIdentifiers, collectCjsExports, exportsRename, requireMainRgx, };
|
package/dist/src/format.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ParseResult } from 'oxc-parser';
|
|
2
|
-
import type { FormatterOptions } from './types.js';
|
|
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/src/module.d.ts
DELETED
package/dist/src/parse.d.ts
DELETED
package/dist/src/specifier.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { ParserOptions, StringLiteral, TemplateLiteral, BinaryExpression, NewExpression, ImportDeclaration, ExportNamedDeclaration, ExportAllDeclaration, TSImportType, ImportExpression, CallExpression } from 'oxc-parser';
|
|
2
|
-
type Spec = {
|
|
3
|
-
type: 'StringLiteral' | 'TemplateLiteral' | 'BinaryExpression' | 'NewExpression';
|
|
4
|
-
node: StringLiteral | TemplateLiteral | BinaryExpression | NewExpression;
|
|
5
|
-
parent: CallExpression | ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression | TSImportType;
|
|
6
|
-
start: number;
|
|
7
|
-
end: number;
|
|
8
|
-
value: string;
|
|
9
|
-
};
|
|
10
|
-
type Callback = (spec: Spec) => string | void;
|
|
11
|
-
declare const specifier: {
|
|
12
|
-
update(path: string, callback: Callback): Promise<string>;
|
|
13
|
-
updateSrc(src: string, lang: ParserOptions["lang"], callback: Callback): Promise<string>;
|
|
14
|
-
};
|
|
15
|
-
export { specifier };
|
|
16
|
-
export type { Spec, Callback };
|