@atlaspack/babel-plugin-transform-contextual-imports 2.16.1-dev-native-compiled-test-712d92d32.0 → 2.16.1
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/CHANGELOG.md +6 -0
- package/dist/index.js +21 -29
- package/lib/index.js +25 -33
- package/lib/types/index.d.ts +2 -6
- package/package.json +2 -3
- package/src/index.ts +27 -42
- package/test/babel-plugin-transform-contextual-imports.test.ts +35 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/LICENSE +0 -201
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @atlaspack/babel-plugin-transform-contextual-imports
|
|
2
2
|
|
|
3
|
+
## 2.16.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#843](https://github.com/atlassian-labs/atlaspack/pull/843) [`f97acf2`](https://github.com/atlassian-labs/atlaspack/commit/f97acf242ed210841db3403d3a5f224f5eff5ab5) Thanks [@nickrobson](https://github.com/nickrobson)! - Transform importCond in JSX, ungate binding-based transform
|
|
8
|
+
|
|
3
9
|
## 2.16.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -67,52 +67,44 @@ exports.default = (0, helper_plugin_utils_1.declare)((api) => {
|
|
|
67
67
|
const [cond, ifTrue, ifFalse] = call.arguments;
|
|
68
68
|
// Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
|
|
69
69
|
path.replaceWithMultiple(buildNodeObject(importId, cond, ifTrue, ifFalse));
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
state.conditionalImportBindings?.add(binding);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
// Add identifier name to set so we can mutate all import usages in the exit pass (legacy approach)
|
|
79
|
-
state.conditionalImportIdentifiers?.add(importId.name);
|
|
70
|
+
// Add the binding to set so we can mutate all references to this binding in the exit pass
|
|
71
|
+
const binding = path.scope.getBinding(importId.name);
|
|
72
|
+
if (binding) {
|
|
73
|
+
state.conditionalImportBindings?.add(binding);
|
|
80
74
|
}
|
|
81
75
|
}
|
|
82
76
|
}
|
|
83
77
|
}
|
|
84
78
|
},
|
|
85
79
|
},
|
|
86
|
-
|
|
80
|
+
ReferencedIdentifier: {
|
|
87
81
|
exit(path, state) {
|
|
82
|
+
if (!isNode(state.opts)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
88
85
|
if (state.visitedIdentifiers?.has(path.node)) {
|
|
89
86
|
return;
|
|
90
87
|
}
|
|
91
|
-
|
|
92
|
-
if (state.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
89
|
+
if (binding && state.conditionalImportBindings?.has(binding)) {
|
|
90
|
+
if (path.isJSXIdentifier()) {
|
|
91
|
+
// Add load property to the import usage
|
|
92
|
+
const newIdentifer = t.jsxIdentifier(path.node.name);
|
|
93
|
+
path.replaceWith(t.jsxMemberExpression(newIdentifer, t.jsxIdentifier('load')));
|
|
94
|
+
state.visitedIdentifiers?.add(newIdentifer);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Add load property to the import usage
|
|
98
|
+
const newIdentifer = t.identifier(path.node.name);
|
|
99
|
+
path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
|
|
100
|
+
state.visitedIdentifiers?.add(newIdentifer);
|
|
96
101
|
}
|
|
97
|
-
const binding = path.scope.getBinding(path.node.name);
|
|
98
|
-
isConditionalImport = !!(binding && state.conditionalImportBindings?.has(binding));
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
// Legacy approach: check identifier names (can cause shadowing issues)
|
|
102
|
-
isConditionalImport = !!state.conditionalImportIdentifiers?.has(path.node.name);
|
|
103
|
-
}
|
|
104
|
-
if (isConditionalImport) {
|
|
105
|
-
// Add load property to the import usage
|
|
106
|
-
const newIdentifer = t.identifier(path.node.name);
|
|
107
|
-
path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
|
|
108
|
-
state.visitedIdentifiers?.add(newIdentifer);
|
|
109
102
|
}
|
|
110
103
|
},
|
|
111
104
|
},
|
|
112
105
|
Program: {
|
|
113
106
|
enter(_, state) {
|
|
114
107
|
state.conditionalImportBindings = new Set();
|
|
115
|
-
state.conditionalImportIdentifiers = new Set();
|
|
116
108
|
state.visitedIdentifiers = new Set();
|
|
117
109
|
},
|
|
118
110
|
},
|
package/lib/index.js
CHANGED
|
@@ -64,56 +64,48 @@ var _default = exports.default = (0, _helperPluginUtils().declare)(api => {
|
|
|
64
64
|
|
|
65
65
|
// Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
|
|
66
66
|
path.replaceWithMultiple(buildNodeObject(importId, cond, ifTrue, ifFalse));
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
} else {
|
|
75
|
-
var _state$conditionalImp2;
|
|
76
|
-
// Add identifier name to set so we can mutate all import usages in the exit pass (legacy approach)
|
|
77
|
-
(_state$conditionalImp2 = state.conditionalImportIdentifiers) === null || _state$conditionalImp2 === void 0 || _state$conditionalImp2.add(importId.name);
|
|
67
|
+
|
|
68
|
+
// Add the binding to set so we can mutate all references to this binding in the exit pass
|
|
69
|
+
const binding = path.scope.getBinding(importId.name);
|
|
70
|
+
if (binding) {
|
|
71
|
+
var _state$conditionalImp;
|
|
72
|
+
(_state$conditionalImp = state.conditionalImportBindings) === null || _state$conditionalImp === void 0 || _state$conditionalImp.add(binding);
|
|
78
73
|
}
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
76
|
}
|
|
82
77
|
}
|
|
83
78
|
},
|
|
84
|
-
|
|
79
|
+
ReferencedIdentifier: {
|
|
85
80
|
exit(path, state) {
|
|
86
|
-
var _state$visitedIdentif2;
|
|
81
|
+
var _state$visitedIdentif2, _state$conditionalImp2;
|
|
82
|
+
if (!isNode(state.opts)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
87
85
|
if ((_state$visitedIdentif2 = state.visitedIdentifiers) !== null && _state$visitedIdentif2 !== void 0 && _state$visitedIdentif2.has(path.node)) {
|
|
88
86
|
return;
|
|
89
87
|
}
|
|
90
|
-
|
|
91
|
-
if (state.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
89
|
+
if (binding && (_state$conditionalImp2 = state.conditionalImportBindings) !== null && _state$conditionalImp2 !== void 0 && _state$conditionalImp2.has(binding)) {
|
|
90
|
+
if (path.isJSXIdentifier()) {
|
|
91
|
+
var _state$visitedIdentif3;
|
|
92
|
+
// Add load property to the import usage
|
|
93
|
+
const newIdentifer = t.jsxIdentifier(path.node.name);
|
|
94
|
+
path.replaceWith(t.jsxMemberExpression(newIdentifer, t.jsxIdentifier('load')));
|
|
95
|
+
(_state$visitedIdentif3 = state.visitedIdentifiers) === null || _state$visitedIdentif3 === void 0 || _state$visitedIdentif3.add(newIdentifer);
|
|
96
|
+
} else {
|
|
97
|
+
var _state$visitedIdentif4;
|
|
98
|
+
// Add load property to the import usage
|
|
99
|
+
const newIdentifer = t.identifier(path.node.name);
|
|
100
|
+
path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
|
|
101
|
+
(_state$visitedIdentif4 = state.visitedIdentifiers) === null || _state$visitedIdentif4 === void 0 || _state$visitedIdentif4.add(newIdentifer);
|
|
96
102
|
}
|
|
97
|
-
const binding = path.scope.getBinding(path.node.name);
|
|
98
|
-
isConditionalImport = !!(binding && (_state$conditionalImp3 = state.conditionalImportBindings) !== null && _state$conditionalImp3 !== void 0 && _state$conditionalImp3.has(binding));
|
|
99
|
-
} else {
|
|
100
|
-
var _state$conditionalImp4;
|
|
101
|
-
// Legacy approach: check identifier names (can cause shadowing issues)
|
|
102
|
-
isConditionalImport = !!((_state$conditionalImp4 = state.conditionalImportIdentifiers) !== null && _state$conditionalImp4 !== void 0 && _state$conditionalImp4.has(path.node.name));
|
|
103
|
-
}
|
|
104
|
-
if (isConditionalImport) {
|
|
105
|
-
var _state$visitedIdentif3;
|
|
106
|
-
// Add load property to the import usage
|
|
107
|
-
const newIdentifer = t.identifier(path.node.name);
|
|
108
|
-
path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
|
|
109
|
-
(_state$visitedIdentif3 = state.visitedIdentifiers) === null || _state$visitedIdentif3 === void 0 || _state$visitedIdentif3.add(newIdentifer);
|
|
110
103
|
}
|
|
111
104
|
}
|
|
112
105
|
},
|
|
113
106
|
Program: {
|
|
114
107
|
enter(_, state) {
|
|
115
108
|
state.conditionalImportBindings = new Set();
|
|
116
|
-
state.conditionalImportIdentifiers = new Set();
|
|
117
109
|
state.visitedIdentifiers = new Set();
|
|
118
110
|
}
|
|
119
111
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -3,18 +3,14 @@ import type { Binding } from '@babel/traverse';
|
|
|
3
3
|
interface Opts {
|
|
4
4
|
/** Use node safe import cond syntax */
|
|
5
5
|
node?: boolean;
|
|
6
|
-
/** Use binding-aware identifier replacement (prevents shadowing issues) */
|
|
7
|
-
useBindingAwareReplacement?: boolean;
|
|
8
6
|
}
|
|
9
7
|
interface State {
|
|
10
8
|
/** Plugin options */
|
|
11
9
|
opts: Opts;
|
|
12
|
-
/** Set of bindings that need to be mutated after import was transformed
|
|
10
|
+
/** Set of bindings that need to be mutated after import was transformed */
|
|
13
11
|
conditionalImportBindings?: Set<Binding>;
|
|
14
|
-
/** Set of identifier names that need to be mutated after import was transformed (legacy approach) */
|
|
15
|
-
conditionalImportIdentifiers?: Set<string>;
|
|
16
12
|
/** Set of identifiers that have been visited in the exit pass, to avoid adding the load property multiple times */
|
|
17
|
-
visitedIdentifiers?: Set<BabelTypes.Identifier>;
|
|
13
|
+
visitedIdentifiers?: Set<BabelTypes.Identifier | BabelTypes.JSXIdentifier>;
|
|
18
14
|
}
|
|
19
15
|
declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => PluginObj<State>;
|
|
20
16
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaspack/babel-plugin-transform-contextual-imports",
|
|
3
|
-
"version": "2.16.1
|
|
3
|
+
"version": "2.16.1",
|
|
4
4
|
"license": "(MIT OR Apache-2.0)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -26,6 +26,5 @@
|
|
|
26
26
|
"type": "commonjs",
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build:lib": "gulp build --gulpfile ../../../gulpfile.js --cwd ."
|
|
29
|
-
}
|
|
30
|
-
"gitHead": "712d92d323f25ef36c76ecd254b8f227fe518b89"
|
|
29
|
+
}
|
|
31
30
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,19 +5,15 @@ import {declare} from '@babel/helper-plugin-utils';
|
|
|
5
5
|
interface Opts {
|
|
6
6
|
/** Use node safe import cond syntax */
|
|
7
7
|
node?: boolean;
|
|
8
|
-
/** Use binding-aware identifier replacement (prevents shadowing issues) */
|
|
9
|
-
useBindingAwareReplacement?: boolean;
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
interface State {
|
|
13
11
|
/** Plugin options */
|
|
14
12
|
opts: Opts;
|
|
15
|
-
/** Set of bindings that need to be mutated after import was transformed
|
|
13
|
+
/** Set of bindings that need to be mutated after import was transformed */
|
|
16
14
|
conditionalImportBindings?: Set<Binding>;
|
|
17
|
-
/** Set of identifier names that need to be mutated after import was transformed (legacy approach) */
|
|
18
|
-
conditionalImportIdentifiers?: Set<string>;
|
|
19
15
|
/** Set of identifiers that have been visited in the exit pass, to avoid adding the load property multiple times */
|
|
20
|
-
visitedIdentifiers?: Set<BabelTypes.Identifier>;
|
|
16
|
+
visitedIdentifiers?: Set<BabelTypes.Identifier | BabelTypes.JSXIdentifier>;
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
const isNode = (opts: Opts): boolean => !!('node' in opts && opts.node);
|
|
@@ -191,60 +187,49 @@ export default declare((api): PluginObj<State> => {
|
|
|
191
187
|
buildNodeObject(importId, cond, ifTrue, ifFalse),
|
|
192
188
|
);
|
|
193
189
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
state.conditionalImportBindings?.add(binding);
|
|
199
|
-
}
|
|
200
|
-
} else {
|
|
201
|
-
// Add identifier name to set so we can mutate all import usages in the exit pass (legacy approach)
|
|
202
|
-
state.conditionalImportIdentifiers?.add(importId.name);
|
|
190
|
+
// Add the binding to set so we can mutate all references to this binding in the exit pass
|
|
191
|
+
const binding = path.scope.getBinding(importId.name);
|
|
192
|
+
if (binding) {
|
|
193
|
+
state.conditionalImportBindings?.add(binding);
|
|
203
194
|
}
|
|
204
195
|
}
|
|
205
196
|
}
|
|
206
197
|
}
|
|
207
198
|
},
|
|
208
199
|
},
|
|
209
|
-
|
|
200
|
+
ReferencedIdentifier: {
|
|
210
201
|
exit(path, state) {
|
|
211
|
-
if (state.
|
|
202
|
+
if (!isNode(state.opts)) {
|
|
212
203
|
return;
|
|
213
204
|
}
|
|
214
205
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (state.opts.useBindingAwareReplacement) {
|
|
218
|
-
// New binding-aware approach: only transform identifiers that are actual references
|
|
219
|
-
if (!path.isReferencedIdentifier()) {
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const binding = path.scope.getBinding(path.node.name);
|
|
224
|
-
isConditionalImport = !!(
|
|
225
|
-
binding && state.conditionalImportBindings?.has(binding)
|
|
226
|
-
);
|
|
227
|
-
} else {
|
|
228
|
-
// Legacy approach: check identifier names (can cause shadowing issues)
|
|
229
|
-
isConditionalImport = !!state.conditionalImportIdentifiers?.has(
|
|
230
|
-
path.node.name,
|
|
231
|
-
);
|
|
206
|
+
if (state.visitedIdentifiers?.has(path.node)) {
|
|
207
|
+
return;
|
|
232
208
|
}
|
|
233
209
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
210
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
211
|
+
if (binding && state.conditionalImportBindings?.has(binding)) {
|
|
212
|
+
if (path.isJSXIdentifier()) {
|
|
213
|
+
// Add load property to the import usage
|
|
214
|
+
const newIdentifer = t.jsxIdentifier(path.node.name);
|
|
215
|
+
path.replaceWith(
|
|
216
|
+
t.jsxMemberExpression(newIdentifer, t.jsxIdentifier('load')),
|
|
217
|
+
);
|
|
218
|
+
state.visitedIdentifiers?.add(newIdentifer);
|
|
219
|
+
} else {
|
|
220
|
+
// Add load property to the import usage
|
|
221
|
+
const newIdentifer = t.identifier(path.node.name);
|
|
222
|
+
path.replaceWith(
|
|
223
|
+
t.memberExpression(newIdentifer, t.identifier('load')),
|
|
224
|
+
);
|
|
225
|
+
state.visitedIdentifiers?.add(newIdentifer);
|
|
226
|
+
}
|
|
241
227
|
}
|
|
242
228
|
},
|
|
243
229
|
},
|
|
244
230
|
Program: {
|
|
245
231
|
enter(_, state) {
|
|
246
232
|
state.conditionalImportBindings = new Set();
|
|
247
|
-
state.conditionalImportIdentifiers = new Set();
|
|
248
233
|
state.visitedIdentifiers = new Set();
|
|
249
234
|
},
|
|
250
235
|
},
|
|
@@ -57,7 +57,7 @@ const jsx = <MyComponent JqlUtils={JqlUtils} />;`;
|
|
|
57
57
|
const result = babel.transformSync(input, {
|
|
58
58
|
configFile: false,
|
|
59
59
|
presets: [],
|
|
60
|
-
plugins: [[plugin, {node: true
|
|
60
|
+
plugins: [[plugin, {node: true}]],
|
|
61
61
|
parserOpts: {
|
|
62
62
|
plugins: ['jsx'],
|
|
63
63
|
},
|
|
@@ -80,13 +80,43 @@ const jsx = <MyComponent JqlUtils={JqlUtils.load} />;`,
|
|
|
80
80
|
);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
it('should
|
|
83
|
+
it('should transform importCond components from legacy runtime transformed JSX', () => {
|
|
84
84
|
const input = `const JqlUtils = importCond('CONDITION', 'IF_TRUE', 'IF_FALSE');
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
const jsx = React.createElement(JqlUtils, null);`;
|
|
86
87
|
const result = babel.transformSync(input, {
|
|
87
88
|
configFile: false,
|
|
88
89
|
presets: [],
|
|
89
|
-
plugins: [[plugin, {node: true
|
|
90
|
+
plugins: [[plugin, {node: true}]],
|
|
91
|
+
parserOpts: {
|
|
92
|
+
plugins: ['jsx'],
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
assert.equal(
|
|
97
|
+
result?.code,
|
|
98
|
+
`const JqlUtils = {
|
|
99
|
+
ifTrue: require('IF_TRUE').default,
|
|
100
|
+
ifFalse: require('IF_FALSE').default
|
|
101
|
+
};
|
|
102
|
+
Object.defineProperty(JqlUtils, "load", {
|
|
103
|
+
get: () => globalThis.__MCOND && globalThis.__MCOND('CONDITION') ? JqlUtils.ifTrue : JqlUtils.ifFalse
|
|
104
|
+
});
|
|
105
|
+
const jsx = React.createElement(JqlUtils.load, null);`,
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should transform importCond components from preserved JSX', () => {
|
|
110
|
+
const input = `const JqlUtils = importCond('CONDITION', 'IF_TRUE', 'IF_FALSE');
|
|
111
|
+
|
|
112
|
+
const jsx = <JqlUtils />;`;
|
|
113
|
+
const result = babel.transformSync(input, {
|
|
114
|
+
configFile: false,
|
|
115
|
+
presets: [],
|
|
116
|
+
plugins: [[plugin, {node: true}]],
|
|
117
|
+
parserOpts: {
|
|
118
|
+
plugins: ['jsx'],
|
|
119
|
+
},
|
|
90
120
|
});
|
|
91
121
|
|
|
92
122
|
assert.equal(
|
|
@@ -98,7 +128,7 @@ const SomeValue = JqlUtils.someProperty;`;
|
|
|
98
128
|
Object.defineProperty(JqlUtils, "load", {
|
|
99
129
|
get: () => globalThis.__MCOND && globalThis.__MCOND('CONDITION') ? JqlUtils.ifTrue : JqlUtils.ifFalse
|
|
100
130
|
});
|
|
101
|
-
const
|
|
131
|
+
const jsx = <JqlUtils.load />;`,
|
|
102
132
|
);
|
|
103
133
|
});
|
|
104
134
|
});
|