@atlaspack/babel-plugin-transform-contextual-imports 2.14.2-noselfbuild-8c516162e.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 ADDED
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ const {
8
+ declare
9
+ } = require('@babel/helper-plugin-utils');
10
+ const isServer = opts => {
11
+ return 'server' in opts && opts.server;
12
+ };
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')) {
21
+ return true;
22
+ } else {
23
+ // Simple error for incorrect syntax (since it's documented with the type)
24
+ throw new Error('importCond must have three string literal arguments');
25
+ }
26
+ }
27
+ return false;
28
+ };
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')));
30
+ const buildNodeObject = (identifier, cond, ifTrue, ifFalse) => [
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')))))])]))];
36
+ const buildServerObject = (identUid, cond, ifTrue, ifFalse) => [
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')))))])]))];
41
+ const checkIsServer = (path, state) => {
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')) {
44
+ const [cond, ifTrue, ifFalse] = path.node.arguments;
45
+ if (isServer(state.opts)) {
46
+ // Make module pass lazy in ssr
47
+ const identUid = path.scope.generateUid(`${cond.value}$${ifTrue.value}$${ifFalse.value}`);
48
+ state.importNodes ??= [];
49
+ state.importNodes.push(...buildServerObject(identUid, cond, ifTrue, ifFalse));
50
+
51
+ // Replace call expression with reference to lazy object getter
52
+ path.replaceWith(t.memberExpression(t.identifier(identUid), t.identifier('load')));
53
+ }
54
+ }
55
+ }
56
+ };
57
+ return {
58
+ name: '@atlaspack/babel-plugin-transform-contextual-imports',
59
+ visitor: {
60
+ CallExpression: {
61
+ enter(path, state) {
62
+ // Preserve server behaviour in deletable code
63
+ checkIsServer(path, state);
64
+ const node = path.node;
65
+ if (isImportCondCallExpression(node)) {
66
+ const [cond, ifTrue, ifFalse] = node.arguments;
67
+ if (!isNode(state.opts)) {
68
+ // Replace the importCond call with a conditional require import, as a fallback for environments that don't support Atlaspack
69
+ path.replaceWith(buildCondFunction(cond, ifTrue, ifFalse));
70
+ }
71
+ }
72
+ }
73
+ },
74
+ VariableDeclaration: {
75
+ enter(path, state) {
76
+ if (isNode(state.opts)) {
77
+ if (path.node.declarations.length === 1 && path.node.declarations[0].type === 'VariableDeclarator' && path.node.declarations[0].id.type === 'Identifier') {
78
+ var _state$visitedIdentif;
79
+ const importId = path.node.declarations[0].id;
80
+ const call = path.node.declarations[0].init;
81
+
82
+ // Mark identifier for object so we don't add the load property to it
83
+ (_state$visitedIdentif = state.visitedIdentifiers) === null || _state$visitedIdentif === void 0 || _state$visitedIdentif.add(importId);
84
+ if (call && isImportCondCallExpression(call)) {
85
+ var _state$conditionalImp;
86
+ const [cond, ifTrue, ifFalse] = call.arguments;
87
+
88
+ // Replace with object containing imports and lazy getter, which allows us to load the correct import based on the condition at runtime
89
+ path.replaceWithMultiple(buildNodeObject(importId, cond, ifTrue, ifFalse));
90
+
91
+ // Add identifier name to set so we can mutate all import usages in the exit pass
92
+ (_state$conditionalImp = state.conditionalImportIdentifiers) === null || _state$conditionalImp === void 0 || _state$conditionalImp.add(importId.name);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ },
98
+ Identifier: {
99
+ exit(path, state) {
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;
104
+ // Add load property to the import usage
105
+ const newIdentifer = t.identifier(path.node.name);
106
+ path.replaceWith(t.memberExpression(newIdentifer, t.identifier('load')));
107
+ (_state$visitedIdentif3 = state.visitedIdentifiers) === null || _state$visitedIdentif3 === void 0 || _state$visitedIdentif3.add(newIdentifer);
108
+ }
109
+ }
110
+ },
111
+ Program: {
112
+ enter(_, state) {
113
+ state.conditionalImportIdentifiers = new Set();
114
+ state.visitedIdentifiers = new Set();
115
+ },
116
+ exit(path, state) {
117
+ if (state.importNodes) {
118
+ // If there's an import node, add it to the top of the body
119
+ path.unshiftContainer('body', state.importNodes);
120
+ }
121
+ }
122
+ }
123
+ }
124
+ };
125
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaspack/babel-plugin-transform-contextual-imports",
3
- "version": "2.14.2-noselfbuild-8c516162e.0",
3
+ "version": "2.14.2-noselfbuild-b8f24f3f8.0",
4
4
  "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -23,5 +23,5 @@
23
23
  "@types/babel__helper-plugin-utils": "^7.10.3"
24
24
  },
25
25
  "type": "commonjs",
26
- "gitHead": "8c516162e3109bbebe535130a7de57e9e59a4eb8"
26
+ "gitHead": "b8f24f3f82b06cb57291e1fa02e9655350bb1ac2"
27
27
  }
@@ -1,43 +1,15 @@
1
- import type {PluginObj, NodePath, types as BabelTypes} from '@babel/core';
2
- import {declare} from '@babel/helper-plugin-utils';
1
+ const {declare} = require('@babel/helper-plugin-utils');
3
2
 
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) => {
3
+ const isServer = (opts) => {
24
4
  return 'server' in opts && opts.server;
25
5
  };
26
6
 
27
- const isNode = (opts: Opts): boolean => !!('node' in opts && opts.node);
7
+ const isNode = (opts) => !!('node' in opts && opts.node);
28
8
 
29
- export default declare((api): PluginObj<State> => {
9
+ export default declare((api) => {
30
10
  const {types: t} = api;
31
11
 
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
- } => {
12
+ const isImportCondCallExpression = (node) => {
41
13
  if (
42
14
  node.type === 'CallExpression' &&
43
15
  node.callee.type === 'Identifier' &&
@@ -45,10 +17,7 @@ export default declare((api): PluginObj<State> => {
45
17
  ) {
46
18
  if (
47
19
  node.arguments.length === 3 &&
48
- node.arguments.every(
49
- (arg): arg is BabelTypes.StringLiteral =>
50
- arg.type === 'StringLiteral',
51
- )
20
+ node.arguments.every((arg) => arg.type === 'StringLiteral')
52
21
  ) {
53
22
  return true;
54
23
  } else {
@@ -60,11 +29,7 @@ export default declare((api): PluginObj<State> => {
60
29
  return false;
61
30
  };
62
31
 
63
- const buildCondFunction = (
64
- cond: BabelTypes.StringLiteral,
65
- ifTrue: BabelTypes.StringLiteral,
66
- ifFalse: BabelTypes.StringLiteral,
67
- ) =>
32
+ const buildCondFunction = (cond, ifTrue, ifFalse) =>
68
33
  t.conditionalExpression(
69
34
  t.logicalExpression(
70
35
  '&&',
@@ -87,12 +52,7 @@ export default declare((api): PluginObj<State> => {
87
52
  ),
88
53
  );
89
54
 
90
- const buildNodeObject = (
91
- identifier: BabelTypes.Identifier,
92
- cond: BabelTypes.StringLiteral,
93
- ifTrue: BabelTypes.StringLiteral,
94
- ifFalse: BabelTypes.StringLiteral,
95
- ) => [
55
+ const buildNodeObject = (identifier, cond, ifTrue, ifFalse) => [
96
56
  // Create object containing imports
97
57
  t.variableDeclaration('const', [
98
58
  t.variableDeclarator(
@@ -158,12 +118,7 @@ export default declare((api): PluginObj<State> => {
158
118
  ),
159
119
  ];
160
120
 
161
- const buildServerObject = (
162
- identUid: string,
163
- cond: BabelTypes.StringLiteral,
164
- ifTrue: BabelTypes.StringLiteral,
165
- ifFalse: BabelTypes.StringLiteral,
166
- ) => [
121
+ const buildServerObject = (identUid, cond, ifTrue, ifFalse) => [
167
122
  // Create object containing imports
168
123
  t.variableDeclaration('const', [
169
124
  t.variableDeclarator(
@@ -234,10 +189,7 @@ export default declare((api): PluginObj<State> => {
234
189
  ),
235
190
  ];
236
191
 
237
- const checkIsServer = (
238
- path: NodePath<BabelTypes.CallExpression>,
239
- state: State,
240
- ) => {
192
+ const checkIsServer = (path, state) => {
241
193
  if (
242
194
  path.node.callee.type === 'Identifier' &&
243
195
  path.node.callee.name === 'importCond'
@@ -1,7 +1,5 @@
1
- // @flow
2
-
3
- import * as babel from '@babel/core';
4
- import assert from 'assert';
1
+ const babel = require('@babel/core');
2
+ const assert = require('assert');
5
3
 
6
4
  const plugin = require.resolve('../src/index.ts');
7
5