@atlaspack/babel-plugin-transform-contextual-imports 2.14.2-noselfbuild-71fe9e998.0 → 2.14.2-noselfbuild-b8f24f3f8.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/lib/index.js +55 -219
- package/package.json +5 -21
- package/{lib/index.mjs → src/index.js} +21 -1
- package/test/babel-plugin-transform-contextual-imports.test.js +2 -4
- package/tsconfig.json +10 -2
- package/lib/index.d.ts +0 -19
- package/src/index.mts +0 -347
package/lib/index.js
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
4
5
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
});
|
|
11
|
-
const _helperpluginutils = require('@babel/helper-plugin-utils');
|
|
12
|
-
const isServer = (opts) => {
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
const {
|
|
8
|
+
declare
|
|
9
|
+
} = require('@babel/helper-plugin-utils');
|
|
10
|
+
const isServer = opts => {
|
|
13
11
|
return 'server' in opts && opts.server;
|
|
14
12
|
};
|
|
15
|
-
const isNode =
|
|
16
|
-
|
|
17
|
-
const {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
node.
|
|
23
|
-
) {
|
|
24
|
-
if (
|
|
25
|
-
node.arguments.length === 3 &&
|
|
26
|
-
node.arguments.every((arg) => arg.type === 'StringLiteral')
|
|
27
|
-
) {
|
|
13
|
+
const isNode = opts => !!('node' in opts && opts.node);
|
|
14
|
+
var _default = exports.default = declare(api => {
|
|
15
|
+
const {
|
|
16
|
+
types: t
|
|
17
|
+
} = api;
|
|
18
|
+
const isImportCondCallExpression = node => {
|
|
19
|
+
if (node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === 'importCond') {
|
|
20
|
+
if (node.arguments.length === 3 && node.arguments.every(arg => arg.type === 'StringLiteral')) {
|
|
28
21
|
return true;
|
|
29
22
|
} else {
|
|
30
23
|
// Simple error for incorrect syntax (since it's documented with the type)
|
|
@@ -33,184 +26,30 @@ const _default = (0, _helperpluginutils.declare)((api) => {
|
|
|
33
26
|
}
|
|
34
27
|
return false;
|
|
35
28
|
};
|
|
36
|
-
const buildCondFunction = (cond, ifTrue, ifFalse) =>
|
|
37
|
-
t.conditionalExpression(
|
|
38
|
-
t.logicalExpression(
|
|
39
|
-
'&&',
|
|
40
|
-
t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')),
|
|
41
|
-
t.callExpression(
|
|
42
|
-
t.memberExpression(
|
|
43
|
-
t.identifier('globalThis'),
|
|
44
|
-
t.identifier('__MCOND'),
|
|
45
|
-
),
|
|
46
|
-
[cond],
|
|
47
|
-
),
|
|
48
|
-
),
|
|
49
|
-
t.memberExpression(
|
|
50
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
51
|
-
t.identifier('default'),
|
|
52
|
-
),
|
|
53
|
-
t.memberExpression(
|
|
54
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
55
|
-
t.identifier('default'),
|
|
56
|
-
),
|
|
57
|
-
);
|
|
29
|
+
const buildCondFunction = (cond, ifTrue, ifFalse) => t.conditionalExpression(t.logicalExpression('&&', t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), t.callExpression(t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), [cond])), t.memberExpression(t.callExpression(t.identifier('require'), [ifTrue]), t.identifier('default')), t.memberExpression(t.callExpression(t.identifier('require'), [ifFalse]), t.identifier('default')));
|
|
58
30
|
const buildNodeObject = (identifier, cond, ifTrue, ifFalse) => [
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
t.objectProperty(
|
|
65
|
-
t.identifier('ifTrue'),
|
|
66
|
-
t.memberExpression(
|
|
67
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
68
|
-
t.identifier('default'),
|
|
69
|
-
),
|
|
70
|
-
),
|
|
71
|
-
t.objectProperty(
|
|
72
|
-
t.identifier('ifFalse'),
|
|
73
|
-
t.memberExpression(
|
|
74
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
75
|
-
t.identifier('default'),
|
|
76
|
-
),
|
|
77
|
-
),
|
|
78
|
-
]),
|
|
79
|
-
),
|
|
80
|
-
]),
|
|
81
|
-
// Create lazy getter via the load property on the object.
|
|
82
|
-
// This is node module resolution safe because each time the import is accessed, we re-evaluate the condition.
|
|
83
|
-
t.expressionStatement(
|
|
84
|
-
t.callExpression(
|
|
85
|
-
t.memberExpression(
|
|
86
|
-
t.identifier('Object'),
|
|
87
|
-
t.identifier('defineProperty'),
|
|
88
|
-
),
|
|
89
|
-
[
|
|
90
|
-
identifier,
|
|
91
|
-
t.stringLiteral('load'),
|
|
92
|
-
t.objectExpression([
|
|
93
|
-
t.objectProperty(
|
|
94
|
-
t.identifier('get'),
|
|
95
|
-
t.arrowFunctionExpression(
|
|
96
|
-
[],
|
|
97
|
-
t.conditionalExpression(
|
|
98
|
-
t.logicalExpression(
|
|
99
|
-
'&&',
|
|
100
|
-
t.memberExpression(
|
|
101
|
-
t.identifier('globalThis'),
|
|
102
|
-
t.identifier('__MCOND'),
|
|
103
|
-
),
|
|
104
|
-
t.callExpression(
|
|
105
|
-
t.memberExpression(
|
|
106
|
-
t.identifier('globalThis'),
|
|
107
|
-
t.identifier('__MCOND'),
|
|
108
|
-
),
|
|
109
|
-
[cond],
|
|
110
|
-
),
|
|
111
|
-
),
|
|
112
|
-
t.memberExpression(identifier, t.identifier('ifTrue')),
|
|
113
|
-
t.memberExpression(identifier, t.identifier('ifFalse')),
|
|
114
|
-
),
|
|
115
|
-
),
|
|
116
|
-
),
|
|
117
|
-
]),
|
|
118
|
-
],
|
|
119
|
-
),
|
|
120
|
-
),
|
|
121
|
-
];
|
|
31
|
+
// Create object containing imports
|
|
32
|
+
t.variableDeclaration('const', [t.variableDeclarator(identifier, t.objectExpression([t.objectProperty(t.identifier('ifTrue'), t.memberExpression(t.callExpression(t.identifier('require'), [ifTrue]), t.identifier('default'))), t.objectProperty(t.identifier('ifFalse'), t.memberExpression(t.callExpression(t.identifier('require'), [ifFalse]), t.identifier('default')))]))]),
|
|
33
|
+
// Create lazy getter via the load property on the object.
|
|
34
|
+
// This is node module resolution safe because each time the import is accessed, we re-evaluate the condition.
|
|
35
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('defineProperty')), [identifier, t.stringLiteral('load'), t.objectExpression([t.objectProperty(t.identifier('get'), t.arrowFunctionExpression([], t.conditionalExpression(t.logicalExpression('&&', t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), t.callExpression(t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), [cond])), t.memberExpression(identifier, t.identifier('ifTrue')), t.memberExpression(identifier, t.identifier('ifFalse')))))])]))];
|
|
122
36
|
const buildServerObject = (identUid, cond, ifTrue, ifFalse) => [
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
t.objectExpression([
|
|
128
|
-
t.objectProperty(
|
|
129
|
-
t.identifier('ifTrue'),
|
|
130
|
-
t.memberExpression(
|
|
131
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
132
|
-
t.identifier('default'),
|
|
133
|
-
),
|
|
134
|
-
),
|
|
135
|
-
t.objectProperty(
|
|
136
|
-
t.identifier('ifFalse'),
|
|
137
|
-
t.memberExpression(
|
|
138
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
139
|
-
t.identifier('default'),
|
|
140
|
-
),
|
|
141
|
-
),
|
|
142
|
-
]),
|
|
143
|
-
),
|
|
144
|
-
]),
|
|
145
|
-
// Create lazy getter via the load property on the object
|
|
146
|
-
t.expressionStatement(
|
|
147
|
-
t.callExpression(
|
|
148
|
-
t.memberExpression(
|
|
149
|
-
t.identifier('Object'),
|
|
150
|
-
t.identifier('defineProperty'),
|
|
151
|
-
),
|
|
152
|
-
[
|
|
153
|
-
t.identifier(identUid),
|
|
154
|
-
t.stringLiteral('load'),
|
|
155
|
-
t.objectExpression([
|
|
156
|
-
t.objectProperty(
|
|
157
|
-
t.identifier('get'),
|
|
158
|
-
t.arrowFunctionExpression(
|
|
159
|
-
[],
|
|
160
|
-
t.conditionalExpression(
|
|
161
|
-
t.logicalExpression(
|
|
162
|
-
'&&',
|
|
163
|
-
t.memberExpression(
|
|
164
|
-
t.identifier('globalThis'),
|
|
165
|
-
t.identifier('__MCOND'),
|
|
166
|
-
),
|
|
167
|
-
t.callExpression(
|
|
168
|
-
t.memberExpression(
|
|
169
|
-
t.identifier('globalThis'),
|
|
170
|
-
t.identifier('__MCOND'),
|
|
171
|
-
),
|
|
172
|
-
[cond],
|
|
173
|
-
),
|
|
174
|
-
),
|
|
175
|
-
t.memberExpression(
|
|
176
|
-
t.identifier(identUid),
|
|
177
|
-
t.identifier('ifTrue'),
|
|
178
|
-
),
|
|
179
|
-
t.memberExpression(
|
|
180
|
-
t.identifier(identUid),
|
|
181
|
-
t.identifier('ifFalse'),
|
|
182
|
-
),
|
|
183
|
-
),
|
|
184
|
-
),
|
|
185
|
-
),
|
|
186
|
-
]),
|
|
187
|
-
],
|
|
188
|
-
),
|
|
189
|
-
),
|
|
190
|
-
];
|
|
37
|
+
// Create object containing imports
|
|
38
|
+
t.variableDeclaration('const', [t.variableDeclarator(t.identifier(identUid), t.objectExpression([t.objectProperty(t.identifier('ifTrue'), t.memberExpression(t.callExpression(t.identifier('require'), [ifTrue]), t.identifier('default'))), t.objectProperty(t.identifier('ifFalse'), t.memberExpression(t.callExpression(t.identifier('require'), [ifFalse]), t.identifier('default')))]))]),
|
|
39
|
+
// Create lazy getter via the load property on the object
|
|
40
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('defineProperty')), [t.identifier(identUid), t.stringLiteral('load'), t.objectExpression([t.objectProperty(t.identifier('get'), t.arrowFunctionExpression([], t.conditionalExpression(t.logicalExpression('&&', t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), t.callExpression(t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')), [cond])), t.memberExpression(t.identifier(identUid), t.identifier('ifTrue')), t.memberExpression(t.identifier(identUid), t.identifier('ifFalse')))))])]))];
|
|
191
41
|
const checkIsServer = (path, state) => {
|
|
192
|
-
if (
|
|
193
|
-
path.node.
|
|
194
|
-
path.node.callee.name === 'importCond'
|
|
195
|
-
) {
|
|
196
|
-
if (
|
|
197
|
-
path.node.arguments.length == 3 &&
|
|
198
|
-
path.node.arguments.every((arg) => arg.type === 'StringLiteral')
|
|
199
|
-
) {
|
|
42
|
+
if (path.node.callee.type === 'Identifier' && path.node.callee.name === 'importCond') {
|
|
43
|
+
if (path.node.arguments.length == 3 && path.node.arguments.every(arg => arg.type === 'StringLiteral')) {
|
|
200
44
|
const [cond, ifTrue, ifFalse] = path.node.arguments;
|
|
201
45
|
if (isServer(state.opts)) {
|
|
202
46
|
// Make module pass lazy in ssr
|
|
203
|
-
const identUid = path.scope.generateUid(
|
|
204
|
-
`${cond.value}$${ifTrue.value}$${ifFalse.value}`,
|
|
205
|
-
);
|
|
47
|
+
const identUid = path.scope.generateUid(`${cond.value}$${ifTrue.value}$${ifFalse.value}`);
|
|
206
48
|
state.importNodes ??= [];
|
|
207
|
-
state.importNodes.push(
|
|
208
|
-
|
|
209
|
-
);
|
|
49
|
+
state.importNodes.push(...buildServerObject(identUid, cond, ifTrue, ifFalse));
|
|
50
|
+
|
|
210
51
|
// Replace call expression with reference to lazy object getter
|
|
211
|
-
path.replaceWith(
|
|
212
|
-
t.memberExpression(t.identifier(identUid), t.identifier('load')),
|
|
213
|
-
);
|
|
52
|
+
path.replaceWith(t.memberExpression(t.identifier(identUid), t.identifier('load')));
|
|
214
53
|
}
|
|
215
54
|
}
|
|
216
55
|
}
|
|
@@ -230,47 +69,44 @@ const _default = (0, _helperpluginutils.declare)((api) => {
|
|
|
230
69
|
path.replaceWith(buildCondFunction(cond, ifTrue, ifFalse));
|
|
231
70
|
}
|
|
232
71
|
}
|
|
233
|
-
}
|
|
72
|
+
}
|
|
234
73
|
},
|
|
235
74
|
VariableDeclaration: {
|
|
236
75
|
enter(path, state) {
|
|
237
76
|
if (isNode(state.opts)) {
|
|
238
|
-
if (
|
|
239
|
-
|
|
240
|
-
path.node.declarations[0].type === 'VariableDeclarator' &&
|
|
241
|
-
path.node.declarations[0].id.type === 'Identifier'
|
|
242
|
-
) {
|
|
77
|
+
if (path.node.declarations.length === 1 && path.node.declarations[0].type === 'VariableDeclarator' && path.node.declarations[0].id.type === 'Identifier') {
|
|
78
|
+
var _state$visitedIdentif;
|
|
243
79
|
const importId = path.node.declarations[0].id;
|
|
244
80
|
const call = path.node.declarations[0].init;
|
|
81
|
+
|
|
245
82
|
// Mark identifier for object so we don't add the load property to it
|
|
246
|
-
state.visitedIdentifiers
|
|
83
|
+
(_state$visitedIdentif = state.visitedIdentifiers) === null || _state$visitedIdentif === void 0 || _state$visitedIdentif.add(importId);
|
|
247
84
|
if (call && isImportCondCallExpression(call)) {
|
|
85
|
+
var _state$conditionalImp;
|
|
248
86
|
const [cond, ifTrue, ifFalse] = call.arguments;
|
|
87
|
+
|
|
249
88
|
// Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
|
|
250
|
-
path.replaceWithMultiple(
|
|
251
|
-
|
|
252
|
-
);
|
|
89
|
+
path.replaceWithMultiple(buildNodeObject(importId, cond, ifTrue, ifFalse));
|
|
90
|
+
|
|
253
91
|
// Add identifier name to set so we can mutate all import usages in the exit pass
|
|
254
|
-
state.conditionalImportIdentifiers
|
|
92
|
+
(_state$conditionalImp = state.conditionalImportIdentifiers) === null || _state$conditionalImp === void 0 || _state$conditionalImp.add(importId.name);
|
|
255
93
|
}
|
|
256
94
|
}
|
|
257
95
|
}
|
|
258
|
-
}
|
|
96
|
+
}
|
|
259
97
|
},
|
|
260
98
|
Identifier: {
|
|
261
99
|
exit(path, state) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
)
|
|
265
|
-
|
|
100
|
+
var _state$conditionalImp2, _state$visitedIdentif2;
|
|
101
|
+
const identifier = (_state$conditionalImp2 = state.conditionalImportIdentifiers) === null || _state$conditionalImp2 === void 0 ? void 0 : _state$conditionalImp2.has(path.node.name);
|
|
102
|
+
if (identifier && !((_state$visitedIdentif2 = state.visitedIdentifiers) !== null && _state$visitedIdentif2 !== void 0 && _state$visitedIdentif2.has(path.node))) {
|
|
103
|
+
var _state$visitedIdentif3;
|
|
266
104
|
// Add load property to the import usage
|
|
267
105
|
const newIdentifer = t.identifier(path.node.name);
|
|
268
|
-
path.replaceWith(
|
|
269
|
-
|
|
270
|
-
);
|
|
271
|
-
state.visitedIdentifiers?.add(newIdentifer);
|
|
106
|
+
path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
|
|
107
|
+
(_state$visitedIdentif3 = state.visitedIdentifiers) === null || _state$visitedIdentif3 === void 0 || _state$visitedIdentif3.add(newIdentifer);
|
|
272
108
|
}
|
|
273
|
-
}
|
|
109
|
+
}
|
|
274
110
|
},
|
|
275
111
|
Program: {
|
|
276
112
|
enter(_, state) {
|
|
@@ -282,8 +118,8 @@ const _default = (0, _helperpluginutils.declare)((api) => {
|
|
|
282
118
|
// If there's an import node, add it to the top of the body
|
|
283
119
|
path.unshiftContainer('body', state.importNodes);
|
|
284
120
|
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
288
124
|
};
|
|
289
|
-
});
|
|
125
|
+
});
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaspack/babel-plugin-transform-contextual-imports",
|
|
3
|
-
"version": "2.14.2-noselfbuild-
|
|
3
|
+
"version": "2.14.2-noselfbuild-b8f24f3f8.0",
|
|
4
4
|
"license": "(MIT OR Apache-2.0)",
|
|
5
|
-
"type": "commonjs",
|
|
6
5
|
"publishConfig": {
|
|
7
6
|
"access": "public"
|
|
8
7
|
},
|
|
@@ -10,27 +9,11 @@
|
|
|
10
9
|
"type": "git",
|
|
11
10
|
"url": "https://github.com/atlassian-labs/atlaspack.git"
|
|
12
11
|
},
|
|
13
|
-
"main": "lib/index.js",
|
|
14
|
-
"
|
|
15
|
-
"exports": {
|
|
16
|
-
".": {
|
|
17
|
-
"atlaspack::sources": "./src/index.mts",
|
|
18
|
-
"types": [
|
|
19
|
-
"./lib/index.d.mts",
|
|
20
|
-
"./src/index.mts"
|
|
21
|
-
],
|
|
22
|
-
"import": "./lib/index.mjs",
|
|
23
|
-
"require": "./lib/index.js",
|
|
24
|
-
"default": "./lib/index.js"
|
|
25
|
-
},
|
|
26
|
-
"./*": "./*"
|
|
27
|
-
},
|
|
12
|
+
"main": "./lib/index.js",
|
|
13
|
+
"source": "./src/index.ts",
|
|
28
14
|
"engines": {
|
|
29
15
|
"node": ">= 16.0.0"
|
|
30
16
|
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build-tsc": "node ../../../scripts/build-tsc.mjs"
|
|
33
|
-
},
|
|
34
17
|
"dependencies": {
|
|
35
18
|
"@babel/core": "^7.12.2",
|
|
36
19
|
"@babel/helper-plugin-utils": "^7.12.2"
|
|
@@ -39,5 +22,6 @@
|
|
|
39
22
|
"@types/babel__core": "^7.12.2",
|
|
40
23
|
"@types/babel__helper-plugin-utils": "^7.10.3"
|
|
41
24
|
},
|
|
42
|
-
"
|
|
25
|
+
"type": "commonjs",
|
|
26
|
+
"gitHead": "b8f24f3f82b06cb57291e1fa02e9655350bb1ac2"
|
|
43
27
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
const {declare} = require('@babel/helper-plugin-utils');
|
|
2
|
+
|
|
2
3
|
const isServer = (opts) => {
|
|
3
4
|
return 'server' in opts && opts.server;
|
|
4
5
|
};
|
|
6
|
+
|
|
5
7
|
const isNode = (opts) => !!('node' in opts && opts.node);
|
|
8
|
+
|
|
6
9
|
export default declare((api) => {
|
|
7
10
|
const {types: t} = api;
|
|
11
|
+
|
|
8
12
|
const isImportCondCallExpression = (node) => {
|
|
9
13
|
if (
|
|
10
14
|
node.type === 'CallExpression' &&
|
|
@@ -21,8 +25,10 @@ export default declare((api) => {
|
|
|
21
25
|
throw new Error('importCond must have three string literal arguments');
|
|
22
26
|
}
|
|
23
27
|
}
|
|
28
|
+
|
|
24
29
|
return false;
|
|
25
30
|
};
|
|
31
|
+
|
|
26
32
|
const buildCondFunction = (cond, ifTrue, ifFalse) =>
|
|
27
33
|
t.conditionalExpression(
|
|
28
34
|
t.logicalExpression(
|
|
@@ -45,6 +51,7 @@ export default declare((api) => {
|
|
|
45
51
|
t.identifier('default'),
|
|
46
52
|
),
|
|
47
53
|
);
|
|
54
|
+
|
|
48
55
|
const buildNodeObject = (identifier, cond, ifTrue, ifFalse) => [
|
|
49
56
|
// Create object containing imports
|
|
50
57
|
t.variableDeclaration('const', [
|
|
@@ -68,6 +75,7 @@ export default declare((api) => {
|
|
|
68
75
|
]),
|
|
69
76
|
),
|
|
70
77
|
]),
|
|
78
|
+
|
|
71
79
|
// Create lazy getter via the load property on the object.
|
|
72
80
|
// This is node module resolution safe because each time the import is accessed, we re-evaluate the condition.
|
|
73
81
|
t.expressionStatement(
|
|
@@ -109,6 +117,7 @@ export default declare((api) => {
|
|
|
109
117
|
),
|
|
110
118
|
),
|
|
111
119
|
];
|
|
120
|
+
|
|
112
121
|
const buildServerObject = (identUid, cond, ifTrue, ifFalse) => [
|
|
113
122
|
// Create object containing imports
|
|
114
123
|
t.variableDeclaration('const', [
|
|
@@ -132,6 +141,7 @@ export default declare((api) => {
|
|
|
132
141
|
]),
|
|
133
142
|
),
|
|
134
143
|
]),
|
|
144
|
+
|
|
135
145
|
// Create lazy getter via the load property on the object
|
|
136
146
|
t.expressionStatement(
|
|
137
147
|
t.callExpression(
|
|
@@ -178,6 +188,7 @@ export default declare((api) => {
|
|
|
178
188
|
),
|
|
179
189
|
),
|
|
180
190
|
];
|
|
191
|
+
|
|
181
192
|
const checkIsServer = (path, state) => {
|
|
182
193
|
if (
|
|
183
194
|
path.node.callee.type === 'Identifier' &&
|
|
@@ -188,15 +199,18 @@ export default declare((api) => {
|
|
|
188
199
|
path.node.arguments.every((arg) => arg.type === 'StringLiteral')
|
|
189
200
|
) {
|
|
190
201
|
const [cond, ifTrue, ifFalse] = path.node.arguments;
|
|
202
|
+
|
|
191
203
|
if (isServer(state.opts)) {
|
|
192
204
|
// Make module pass lazy in ssr
|
|
193
205
|
const identUid = path.scope.generateUid(
|
|
194
206
|
`${cond.value}$${ifTrue.value}$${ifFalse.value}`,
|
|
195
207
|
);
|
|
208
|
+
|
|
196
209
|
state.importNodes ??= [];
|
|
197
210
|
state.importNodes.push(
|
|
198
211
|
...buildServerObject(identUid, cond, ifTrue, ifFalse),
|
|
199
212
|
);
|
|
213
|
+
|
|
200
214
|
// Replace call expression with reference to lazy object getter
|
|
201
215
|
path.replaceWith(
|
|
202
216
|
t.memberExpression(t.identifier(identUid), t.identifier('load')),
|
|
@@ -205,6 +219,7 @@ export default declare((api) => {
|
|
|
205
219
|
}
|
|
206
220
|
}
|
|
207
221
|
};
|
|
222
|
+
|
|
208
223
|
return {
|
|
209
224
|
name: '@atlaspack/babel-plugin-transform-contextual-imports',
|
|
210
225
|
visitor: {
|
|
@@ -212,6 +227,7 @@ export default declare((api) => {
|
|
|
212
227
|
enter(path, state) {
|
|
213
228
|
// Preserve server behaviour in deletable code
|
|
214
229
|
checkIsServer(path, state);
|
|
230
|
+
|
|
215
231
|
const node = path.node;
|
|
216
232
|
if (isImportCondCallExpression(node)) {
|
|
217
233
|
const [cond, ifTrue, ifFalse] = node.arguments;
|
|
@@ -232,14 +248,18 @@ export default declare((api) => {
|
|
|
232
248
|
) {
|
|
233
249
|
const importId = path.node.declarations[0].id;
|
|
234
250
|
const call = path.node.declarations[0].init;
|
|
251
|
+
|
|
235
252
|
// Mark identifier for object so we don't add the load property to it
|
|
236
253
|
state.visitedIdentifiers?.add(importId);
|
|
254
|
+
|
|
237
255
|
if (call && isImportCondCallExpression(call)) {
|
|
238
256
|
const [cond, ifTrue, ifFalse] = call.arguments;
|
|
257
|
+
|
|
239
258
|
// Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
|
|
240
259
|
path.replaceWithMultiple(
|
|
241
260
|
buildNodeObject(importId, cond, ifTrue, ifFalse),
|
|
242
261
|
);
|
|
262
|
+
|
|
243
263
|
// Add identifier name to set so we can mutate all import usages in the exit pass
|
|
244
264
|
state.conditionalImportIdentifiers?.add(importId.name);
|
|
245
265
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2016",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"esModuleInterop": true,
|
|
6
|
+
"forceConsistentCasingInFileNames": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/*"],
|
|
11
|
+
"exclude": ["node_modules"]
|
|
4
12
|
}
|
package/lib/index.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { PluginObj, types as BabelTypes } from '@babel/core';
|
|
2
|
-
interface Opts {
|
|
3
|
-
/** @deprecated Use "node" instead */
|
|
4
|
-
server?: boolean;
|
|
5
|
-
/** Use node safe import cond syntax */
|
|
6
|
-
node?: boolean;
|
|
7
|
-
}
|
|
8
|
-
interface State {
|
|
9
|
-
/** Plugin options */
|
|
10
|
-
opts: Opts;
|
|
11
|
-
/** @deprecated Statement types didn't work so using any */
|
|
12
|
-
importNodes?: any[];
|
|
13
|
-
/** Set of identifier names that need to be mutated after import was transformed */
|
|
14
|
-
conditionalImportIdentifiers?: Set<string>;
|
|
15
|
-
/** Set of identifiers that have been visited in the exit pass, to avoid adding the load property multiple times */
|
|
16
|
-
visitedIdentifiers?: Set<BabelTypes.Identifier>;
|
|
17
|
-
}
|
|
18
|
-
declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => PluginObj<State>;
|
|
19
|
-
export default _default;
|
package/src/index.mts
DELETED
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import type {PluginObj, NodePath, types as BabelTypes} from '@babel/core';
|
|
2
|
-
import {declare} from '@babel/helper-plugin-utils';
|
|
3
|
-
|
|
4
|
-
interface Opts {
|
|
5
|
-
/** @deprecated Use "node" instead */
|
|
6
|
-
server?: boolean;
|
|
7
|
-
/** Use node safe import cond syntax */
|
|
8
|
-
node?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface State {
|
|
12
|
-
/** Plugin options */
|
|
13
|
-
opts: Opts;
|
|
14
|
-
/** @deprecated Statement types didn't work so using any */
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
-
importNodes?: any[];
|
|
17
|
-
/** Set of identifier names that need to be mutated after import was transformed */
|
|
18
|
-
conditionalImportIdentifiers?: Set<string>;
|
|
19
|
-
/** Set of identifiers that have been visited in the exit pass, to avoid adding the load property multiple times */
|
|
20
|
-
visitedIdentifiers?: Set<BabelTypes.Identifier>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const isServer = (opts: Opts) => {
|
|
24
|
-
return 'server' in opts && opts.server;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const isNode = (opts: Opts): boolean => !!('node' in opts && opts.node);
|
|
28
|
-
|
|
29
|
-
export default declare((api): PluginObj<State> => {
|
|
30
|
-
const {types: t} = api;
|
|
31
|
-
|
|
32
|
-
const isImportCondCallExpression = (
|
|
33
|
-
node: BabelTypes.Node,
|
|
34
|
-
): node is BabelTypes.CallExpression & {
|
|
35
|
-
arguments: [
|
|
36
|
-
BabelTypes.StringLiteral,
|
|
37
|
-
BabelTypes.StringLiteral,
|
|
38
|
-
BabelTypes.StringLiteral,
|
|
39
|
-
];
|
|
40
|
-
} => {
|
|
41
|
-
if (
|
|
42
|
-
node.type === 'CallExpression' &&
|
|
43
|
-
node.callee.type === 'Identifier' &&
|
|
44
|
-
node.callee.name === 'importCond'
|
|
45
|
-
) {
|
|
46
|
-
if (
|
|
47
|
-
node.arguments.length === 3 &&
|
|
48
|
-
node.arguments.every(
|
|
49
|
-
(arg): arg is BabelTypes.StringLiteral =>
|
|
50
|
-
arg.type === 'StringLiteral',
|
|
51
|
-
)
|
|
52
|
-
) {
|
|
53
|
-
return true;
|
|
54
|
-
} else {
|
|
55
|
-
// Simple error for incorrect syntax (since it's documented with the type)
|
|
56
|
-
throw new Error('importCond must have three string literal arguments');
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return false;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const buildCondFunction = (
|
|
64
|
-
cond: BabelTypes.StringLiteral,
|
|
65
|
-
ifTrue: BabelTypes.StringLiteral,
|
|
66
|
-
ifFalse: BabelTypes.StringLiteral,
|
|
67
|
-
) =>
|
|
68
|
-
t.conditionalExpression(
|
|
69
|
-
t.logicalExpression(
|
|
70
|
-
'&&',
|
|
71
|
-
t.memberExpression(t.identifier('globalThis'), t.identifier('__MCOND')),
|
|
72
|
-
t.callExpression(
|
|
73
|
-
t.memberExpression(
|
|
74
|
-
t.identifier('globalThis'),
|
|
75
|
-
t.identifier('__MCOND'),
|
|
76
|
-
),
|
|
77
|
-
[cond],
|
|
78
|
-
),
|
|
79
|
-
),
|
|
80
|
-
t.memberExpression(
|
|
81
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
82
|
-
t.identifier('default'),
|
|
83
|
-
),
|
|
84
|
-
t.memberExpression(
|
|
85
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
86
|
-
t.identifier('default'),
|
|
87
|
-
),
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const buildNodeObject = (
|
|
91
|
-
identifier: BabelTypes.Identifier,
|
|
92
|
-
cond: BabelTypes.StringLiteral,
|
|
93
|
-
ifTrue: BabelTypes.StringLiteral,
|
|
94
|
-
ifFalse: BabelTypes.StringLiteral,
|
|
95
|
-
) => [
|
|
96
|
-
// Create object containing imports
|
|
97
|
-
t.variableDeclaration('const', [
|
|
98
|
-
t.variableDeclarator(
|
|
99
|
-
identifier,
|
|
100
|
-
t.objectExpression([
|
|
101
|
-
t.objectProperty(
|
|
102
|
-
t.identifier('ifTrue'),
|
|
103
|
-
t.memberExpression(
|
|
104
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
105
|
-
t.identifier('default'),
|
|
106
|
-
),
|
|
107
|
-
),
|
|
108
|
-
t.objectProperty(
|
|
109
|
-
t.identifier('ifFalse'),
|
|
110
|
-
t.memberExpression(
|
|
111
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
112
|
-
t.identifier('default'),
|
|
113
|
-
),
|
|
114
|
-
),
|
|
115
|
-
]),
|
|
116
|
-
),
|
|
117
|
-
]),
|
|
118
|
-
|
|
119
|
-
// Create lazy getter via the load property on the object.
|
|
120
|
-
// This is node module resolution safe because each time the import is accessed, we re-evaluate the condition.
|
|
121
|
-
t.expressionStatement(
|
|
122
|
-
t.callExpression(
|
|
123
|
-
t.memberExpression(
|
|
124
|
-
t.identifier('Object'),
|
|
125
|
-
t.identifier('defineProperty'),
|
|
126
|
-
),
|
|
127
|
-
[
|
|
128
|
-
identifier,
|
|
129
|
-
t.stringLiteral('load'),
|
|
130
|
-
t.objectExpression([
|
|
131
|
-
t.objectProperty(
|
|
132
|
-
t.identifier('get'),
|
|
133
|
-
t.arrowFunctionExpression(
|
|
134
|
-
[],
|
|
135
|
-
t.conditionalExpression(
|
|
136
|
-
t.logicalExpression(
|
|
137
|
-
'&&',
|
|
138
|
-
t.memberExpression(
|
|
139
|
-
t.identifier('globalThis'),
|
|
140
|
-
t.identifier('__MCOND'),
|
|
141
|
-
),
|
|
142
|
-
t.callExpression(
|
|
143
|
-
t.memberExpression(
|
|
144
|
-
t.identifier('globalThis'),
|
|
145
|
-
t.identifier('__MCOND'),
|
|
146
|
-
),
|
|
147
|
-
[cond],
|
|
148
|
-
),
|
|
149
|
-
),
|
|
150
|
-
t.memberExpression(identifier, t.identifier('ifTrue')),
|
|
151
|
-
t.memberExpression(identifier, t.identifier('ifFalse')),
|
|
152
|
-
),
|
|
153
|
-
),
|
|
154
|
-
),
|
|
155
|
-
]),
|
|
156
|
-
],
|
|
157
|
-
),
|
|
158
|
-
),
|
|
159
|
-
];
|
|
160
|
-
|
|
161
|
-
const buildServerObject = (
|
|
162
|
-
identUid: string,
|
|
163
|
-
cond: BabelTypes.StringLiteral,
|
|
164
|
-
ifTrue: BabelTypes.StringLiteral,
|
|
165
|
-
ifFalse: BabelTypes.StringLiteral,
|
|
166
|
-
) => [
|
|
167
|
-
// Create object containing imports
|
|
168
|
-
t.variableDeclaration('const', [
|
|
169
|
-
t.variableDeclarator(
|
|
170
|
-
t.identifier(identUid),
|
|
171
|
-
t.objectExpression([
|
|
172
|
-
t.objectProperty(
|
|
173
|
-
t.identifier('ifTrue'),
|
|
174
|
-
t.memberExpression(
|
|
175
|
-
t.callExpression(t.identifier('require'), [ifTrue]),
|
|
176
|
-
t.identifier('default'),
|
|
177
|
-
),
|
|
178
|
-
),
|
|
179
|
-
t.objectProperty(
|
|
180
|
-
t.identifier('ifFalse'),
|
|
181
|
-
t.memberExpression(
|
|
182
|
-
t.callExpression(t.identifier('require'), [ifFalse]),
|
|
183
|
-
t.identifier('default'),
|
|
184
|
-
),
|
|
185
|
-
),
|
|
186
|
-
]),
|
|
187
|
-
),
|
|
188
|
-
]),
|
|
189
|
-
|
|
190
|
-
// Create lazy getter via the load property on the object
|
|
191
|
-
t.expressionStatement(
|
|
192
|
-
t.callExpression(
|
|
193
|
-
t.memberExpression(
|
|
194
|
-
t.identifier('Object'),
|
|
195
|
-
t.identifier('defineProperty'),
|
|
196
|
-
),
|
|
197
|
-
[
|
|
198
|
-
t.identifier(identUid),
|
|
199
|
-
t.stringLiteral('load'),
|
|
200
|
-
t.objectExpression([
|
|
201
|
-
t.objectProperty(
|
|
202
|
-
t.identifier('get'),
|
|
203
|
-
t.arrowFunctionExpression(
|
|
204
|
-
[],
|
|
205
|
-
t.conditionalExpression(
|
|
206
|
-
t.logicalExpression(
|
|
207
|
-
'&&',
|
|
208
|
-
t.memberExpression(
|
|
209
|
-
t.identifier('globalThis'),
|
|
210
|
-
t.identifier('__MCOND'),
|
|
211
|
-
),
|
|
212
|
-
t.callExpression(
|
|
213
|
-
t.memberExpression(
|
|
214
|
-
t.identifier('globalThis'),
|
|
215
|
-
t.identifier('__MCOND'),
|
|
216
|
-
),
|
|
217
|
-
[cond],
|
|
218
|
-
),
|
|
219
|
-
),
|
|
220
|
-
t.memberExpression(
|
|
221
|
-
t.identifier(identUid),
|
|
222
|
-
t.identifier('ifTrue'),
|
|
223
|
-
),
|
|
224
|
-
t.memberExpression(
|
|
225
|
-
t.identifier(identUid),
|
|
226
|
-
t.identifier('ifFalse'),
|
|
227
|
-
),
|
|
228
|
-
),
|
|
229
|
-
),
|
|
230
|
-
),
|
|
231
|
-
]),
|
|
232
|
-
],
|
|
233
|
-
),
|
|
234
|
-
),
|
|
235
|
-
];
|
|
236
|
-
|
|
237
|
-
const checkIsServer = (
|
|
238
|
-
path: NodePath<BabelTypes.CallExpression>,
|
|
239
|
-
state: State,
|
|
240
|
-
) => {
|
|
241
|
-
if (
|
|
242
|
-
path.node.callee.type === 'Identifier' &&
|
|
243
|
-
path.node.callee.name === 'importCond'
|
|
244
|
-
) {
|
|
245
|
-
if (
|
|
246
|
-
path.node.arguments.length == 3 &&
|
|
247
|
-
path.node.arguments.every((arg) => arg.type === 'StringLiteral')
|
|
248
|
-
) {
|
|
249
|
-
const [cond, ifTrue, ifFalse] = path.node.arguments;
|
|
250
|
-
|
|
251
|
-
if (isServer(state.opts)) {
|
|
252
|
-
// Make module pass lazy in ssr
|
|
253
|
-
const identUid = path.scope.generateUid(
|
|
254
|
-
`${cond.value}$${ifTrue.value}$${ifFalse.value}`,
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
state.importNodes ??= [];
|
|
258
|
-
state.importNodes.push(
|
|
259
|
-
...buildServerObject(identUid, cond, ifTrue, ifFalse),
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
// Replace call expression with reference to lazy object getter
|
|
263
|
-
path.replaceWith(
|
|
264
|
-
t.memberExpression(t.identifier(identUid), t.identifier('load')),
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
return {
|
|
272
|
-
name: '@atlaspack/babel-plugin-transform-contextual-imports',
|
|
273
|
-
visitor: {
|
|
274
|
-
CallExpression: {
|
|
275
|
-
enter(path, state) {
|
|
276
|
-
// Preserve server behaviour in deletable code
|
|
277
|
-
checkIsServer(path, state);
|
|
278
|
-
|
|
279
|
-
const node = path.node;
|
|
280
|
-
if (isImportCondCallExpression(node)) {
|
|
281
|
-
const [cond, ifTrue, ifFalse] = node.arguments;
|
|
282
|
-
if (!isNode(state.opts)) {
|
|
283
|
-
// Replace the importCond call with a conditional require import, as a fallback for environments that don't support Atlaspack
|
|
284
|
-
path.replaceWith(buildCondFunction(cond, ifTrue, ifFalse));
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
VariableDeclaration: {
|
|
290
|
-
enter(path, state) {
|
|
291
|
-
if (isNode(state.opts)) {
|
|
292
|
-
if (
|
|
293
|
-
path.node.declarations.length === 1 &&
|
|
294
|
-
path.node.declarations[0].type === 'VariableDeclarator' &&
|
|
295
|
-
path.node.declarations[0].id.type === 'Identifier'
|
|
296
|
-
) {
|
|
297
|
-
const importId = path.node.declarations[0].id;
|
|
298
|
-
const call = path.node.declarations[0].init;
|
|
299
|
-
|
|
300
|
-
// Mark identifier for object so we don't add the load property to it
|
|
301
|
-
state.visitedIdentifiers?.add(importId);
|
|
302
|
-
|
|
303
|
-
if (call && isImportCondCallExpression(call)) {
|
|
304
|
-
const [cond, ifTrue, ifFalse] = call.arguments;
|
|
305
|
-
|
|
306
|
-
// Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
|
|
307
|
-
path.replaceWithMultiple(
|
|
308
|
-
buildNodeObject(importId, cond, ifTrue, ifFalse),
|
|
309
|
-
);
|
|
310
|
-
|
|
311
|
-
// Add identifier name to set so we can mutate all import usages in the exit pass
|
|
312
|
-
state.conditionalImportIdentifiers?.add(importId.name);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
},
|
|
317
|
-
},
|
|
318
|
-
Identifier: {
|
|
319
|
-
exit(path, state) {
|
|
320
|
-
const identifier = state.conditionalImportIdentifiers?.has(
|
|
321
|
-
path.node.name,
|
|
322
|
-
);
|
|
323
|
-
if (identifier && !state.visitedIdentifiers?.has(path.node)) {
|
|
324
|
-
// Add load property to the import usage
|
|
325
|
-
const newIdentifer = t.identifier(path.node.name);
|
|
326
|
-
path.replaceWith(
|
|
327
|
-
t.memberExpression(newIdentifer, t.identifier('load')),
|
|
328
|
-
);
|
|
329
|
-
state.visitedIdentifiers?.add(newIdentifer);
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
Program: {
|
|
334
|
-
enter(_, state) {
|
|
335
|
-
state.conditionalImportIdentifiers = new Set();
|
|
336
|
-
state.visitedIdentifiers = new Set();
|
|
337
|
-
},
|
|
338
|
-
exit(path, state) {
|
|
339
|
-
if (state.importNodes) {
|
|
340
|
-
// If there's an import node, add it to the top of the body
|
|
341
|
-
path.unshiftContainer('body', state.importNodes);
|
|
342
|
-
}
|
|
343
|
-
},
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
};
|
|
347
|
-
});
|