ember-vite-hmr 2.2.4 → 2.4.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 +31 -0
- package/dist/instance-initializers/setup-hmr-manager.js +42 -3
- package/dist/instance-initializers/setup-hmr-manager.js.map +1 -1
- package/dist/lib/babel-plugin/private-members.d.ts +3 -0
- package/dist/lib/babel-plugin/private-members.js +291 -0
- package/dist/lib/babel-plugin/service-proxy.d.ts +3 -0
- package/dist/lib/babel-plugin/service-proxy.js +300 -0
- package/dist/lib/babel-plugin/template-imports.d.ts +46 -0
- package/dist/lib/babel-plugin/template-imports.js +250 -0
- package/dist/lib/babel-plugin.d.ts +3 -31
- package/dist/lib/babel-plugin.js +45 -352
- package/dist/lib/hmr.js +337 -124
- package/package.json +6 -5
package/dist/lib/babel-plugin.js
CHANGED
|
@@ -1,143 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
var _a;
|
|
25
|
-
if (process.env.EMBER_VITE_HMR_ENABLED !== 'true') {
|
|
26
|
-
return {
|
|
27
|
-
visitor: {},
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
if ((_a = env.filename) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
|
|
31
|
-
return {
|
|
32
|
-
visitor: {},
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
const meta = this.meta;
|
|
36
|
-
const importVar = env.meta.jsutils.bindExpression(meta.importVar || 'null', null, {
|
|
37
|
-
nameHint: 'template__imports__',
|
|
38
|
-
});
|
|
39
|
-
meta.importVar = meta.importVar || importVar;
|
|
40
|
-
return {
|
|
41
|
-
visitor: Object.assign({}, this.buildVisitor({
|
|
42
|
-
importVar,
|
|
43
|
-
importBindings: meta.importBindings,
|
|
44
|
-
babelProgram: meta.babelProgram,
|
|
45
|
-
})),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
buildVisitor({ importVar, importBindings, babelProgram, }) {
|
|
49
|
-
const findImport = function findImport(specifier) {
|
|
50
|
-
return babelProgram.body.find((b) => b.type === 'ImportDeclaration' &&
|
|
51
|
-
b.specifiers.some((s) => s.local.name === specifier));
|
|
52
|
-
};
|
|
53
|
-
const findBlockParams = function (expression, p) {
|
|
54
|
-
if (p.node.type === 'Template') {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
if (p.node &&
|
|
58
|
-
p.node.type === 'BlockStatement' &&
|
|
59
|
-
p.node.program.blockParams.includes(expression)) {
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
const node = p.node;
|
|
63
|
-
if (node && node.blockParams && node.blockParams.includes(expression)) {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
if (!p.parent)
|
|
67
|
-
return false;
|
|
68
|
-
return findBlockParams(expression, p.parent);
|
|
69
|
-
};
|
|
70
|
-
const visitor = {
|
|
71
|
-
PathExpression: (node, p) => {
|
|
72
|
-
var _a, _b;
|
|
73
|
-
if ((((_a = p.parentNode) === null || _a === void 0 ? void 0 : _a.type) === 'SubExpression' ||
|
|
74
|
-
((_b = p.parentNode) === null || _b === void 0 ? void 0 : _b.type) === 'MustacheStatement') &&
|
|
75
|
-
p.parentNode.params.includes(node)) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const original = node.original.split('.')[0];
|
|
79
|
-
if (original === 'this')
|
|
80
|
-
return;
|
|
81
|
-
if (original.startsWith('@'))
|
|
82
|
-
return;
|
|
83
|
-
if (original === 'block')
|
|
84
|
-
return;
|
|
85
|
-
if (original.startsWith('this.'))
|
|
86
|
-
return;
|
|
87
|
-
if (findBlockParams(original, p))
|
|
88
|
-
return;
|
|
89
|
-
if (node.original === 'helper' ||
|
|
90
|
-
node.original === 'component' ||
|
|
91
|
-
node.original === 'modifier') {
|
|
92
|
-
// node.original;
|
|
93
|
-
const parent = p.parentNode;
|
|
94
|
-
if (typeof parent.params[0].original !==
|
|
95
|
-
'string') {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const original = parent.params[0].original.split('.')[0];
|
|
99
|
-
if (original && findBlockParams(original, p))
|
|
100
|
-
return;
|
|
101
|
-
if (original === null || original === void 0 ? void 0 : original.includes('.'))
|
|
102
|
-
return;
|
|
103
|
-
if (!original)
|
|
104
|
-
return;
|
|
105
|
-
if (findImport(original)) {
|
|
106
|
-
const param = glimmer.builders.path(`${importVar}.${original}`);
|
|
107
|
-
parent.params.splice(0, 1, param);
|
|
108
|
-
importBindings.add(original);
|
|
109
|
-
}
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (importVar) {
|
|
113
|
-
if (findImport(node.original)) {
|
|
114
|
-
node.original = `${importVar}.${node.original}`;
|
|
115
|
-
node.parts = node.original.split('.');
|
|
116
|
-
importBindings.add(original);
|
|
117
|
-
}
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
ElementNode: (element, p) => {
|
|
122
|
-
const original = element.tag.split('.')[0];
|
|
123
|
-
if (findBlockParams(original, p))
|
|
124
|
-
return;
|
|
125
|
-
if (importVar) {
|
|
126
|
-
if (findImport(original)) {
|
|
127
|
-
element.tag = `${importVar}.${original}`;
|
|
128
|
-
p.node.tag = element.tag;
|
|
129
|
-
importBindings.add(original);
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
return visitor;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
export const hotAstProcessor = new HotAstProcessor();
|
|
1
|
+
import { hotAstProcessor, finalizeTemplateImports, hmrImportMetadataCache, normalizeHmrCacheFilename, } from './babel-plugin/template-imports.js';
|
|
2
|
+
import { renamePrivateClassMembers } from './babel-plugin/private-members.js';
|
|
3
|
+
import { transformServiceExport } from './babel-plugin/service-proxy.js';
|
|
4
|
+
// `ember-vite-hmr/lib/babel-plugin` is a published subpath import (see
|
|
5
|
+
// test-app/babel.config.mjs), so this file's module path and its exports
|
|
6
|
+
// (this default export, and the `hotAstProcessor` / `hmrImportMetadataCache`
|
|
7
|
+
// / `normalizeHmrCacheFilename` re-exports below) have to keep resolving
|
|
8
|
+
// exactly as-is -- the actual logic lives in ./babel-plugin/*, split by
|
|
9
|
+
// concern:
|
|
10
|
+
// - template-imports.ts: rewrites template references to imported
|
|
11
|
+
// components/helpers/modifiers through a per-module tracked class, so
|
|
12
|
+
// swapping which module a virtual HMR wrapper resolves to is visible to
|
|
13
|
+
// templates (registered separately as an ember-template-compilation
|
|
14
|
+
// transform via the `hotAstProcessor` export below), and shares the
|
|
15
|
+
// computed import metadata with lib/hmr.ts via `hmrImportMetadataCache`.
|
|
16
|
+
// - private-members.ts: rewrites every native `#private` class member the
|
|
17
|
+
// app's own source declares to a plain, uniquely-named property, so it
|
|
18
|
+
// reads/writes correctly through the service proxy below regardless of
|
|
19
|
+
// what `this` is at the call site.
|
|
20
|
+
// - service-proxy.ts: rewrites `export default class X extends Service`
|
|
21
|
+
// into a generated HMR proxy class that swaps its delegate instance on
|
|
22
|
+
// every accepted update.
|
|
23
|
+
export { hotAstProcessor, hmrImportMetadataCache, normalizeHmrCacheFilename };
|
|
139
24
|
export default function hotReplaceAst(babel) {
|
|
140
|
-
const t = babel.types;
|
|
141
25
|
return {
|
|
142
26
|
name: 'a-hot-reload-imports',
|
|
143
27
|
pre(file) {
|
|
@@ -145,202 +29,31 @@ export default function hotReplaceAst(babel) {
|
|
|
145
29
|
hotAstProcessor.meta.babelProgram = file.ast.program;
|
|
146
30
|
},
|
|
147
31
|
visitor: {
|
|
148
|
-
|
|
149
|
-
|
|
32
|
+
// Runs on *every* class the app's own source defines, independent of
|
|
33
|
+
// whether it's a service, a service's ancestor, or unrelated to the
|
|
34
|
+
// HMR proxy machinery entirely -- see `renamePrivateClassMembers`'s
|
|
35
|
+
// own doc comment for why this can't be scoped any tighter than that
|
|
36
|
+
// without whole-program analysis. This also visits the `proxyClass`
|
|
37
|
+
// (and, for an inline export, the `originalClass` copy)
|
|
38
|
+
// `transformServiceExport` generates below -- harmless today only
|
|
39
|
+
// because generated proxy classes never declare private members of
|
|
40
|
+
// their own; if that ever changes, this visitor would rename them
|
|
41
|
+
// too.
|
|
42
|
+
Class(path, state) {
|
|
43
|
+
var _a;
|
|
150
44
|
if (process.env.EMBER_VITE_HMR_ENABLED !== 'true') {
|
|
151
45
|
return;
|
|
152
46
|
}
|
|
153
47
|
if ((_a = state.filename) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
|
|
154
48
|
return;
|
|
155
49
|
}
|
|
156
|
-
// Check if this is a service file (normalize path for cross-platform compatibility)
|
|
157
|
-
const normalizedFilename = (_b = state.filename) === null || _b === void 0 ? void 0 : _b.replace(/\\/g, '/');
|
|
158
|
-
if (!(normalizedFilename === null || normalizedFilename === void 0 ? void 0 : normalizedFilename.includes('/services/'))) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const declaration = path.node.declaration;
|
|
162
|
-
// Handle both inline class declaration and identifier reference
|
|
163
|
-
let classDeclaration = null;
|
|
164
|
-
let classIdentifier = null;
|
|
165
|
-
if (declaration.type === 'ClassDeclaration' && declaration.id) {
|
|
166
|
-
// Case 1: export default class MyService extends Service { ... }
|
|
167
|
-
classDeclaration = declaration;
|
|
168
|
-
classIdentifier = declaration.id;
|
|
169
|
-
}
|
|
170
|
-
else if (declaration.type === 'Identifier') {
|
|
171
|
-
// Case 2: class MyService extends Service { ... } \n export default MyService;
|
|
172
|
-
const binding = path.scope.getBinding(declaration.name);
|
|
173
|
-
if (binding && binding.path.isClassDeclaration()) {
|
|
174
|
-
classDeclaration = binding.path
|
|
175
|
-
.node;
|
|
176
|
-
classIdentifier = classDeclaration.id;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (!classDeclaration || !classIdentifier) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (classIdentifier.name.endsWith('HmrProxy')) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
// Check if it extends Service
|
|
186
|
-
const superClass = classDeclaration.superClass;
|
|
187
|
-
if (!superClass ||
|
|
188
|
-
((superClass.type !== 'Identifier' ||
|
|
189
|
-
superClass.name !== 'Service') &&
|
|
190
|
-
superClass.type !== 'MemberExpression')) {
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
// Get the program path for ImportUtil
|
|
194
50
|
const programPath = path.findParent((p) => p.isProgram());
|
|
195
51
|
if (!programPath) {
|
|
196
52
|
return;
|
|
197
53
|
}
|
|
198
|
-
|
|
199
|
-
const tracked = util.import(programPath, '@glimmer/tracking', 'tracked');
|
|
200
|
-
const Service = util.import(programPath, '@ember/service', 'default');
|
|
201
|
-
const originalClassName = classIdentifier.name;
|
|
202
|
-
const proxyClassName = `${originalClassName}HmrProxy`;
|
|
203
|
-
// Keep the original class as-is, just remove it from export
|
|
204
|
-
// We'll add it back as a non-exported class
|
|
205
|
-
const babelTemplate = babel.template;
|
|
206
|
-
// The live proxy instance and the latest accepted implementation must
|
|
207
|
-
// live on `import.meta.hot.data`, not in a module-scope `let`: Vite
|
|
208
|
-
// guarantees that object (and only that object) survives across a
|
|
209
|
-
// module's hot re-evaluations. A component's `@service` injection can
|
|
210
|
-
// end up constructing the proxy against a *later* re-evaluation of
|
|
211
|
-
// this module than the one whose `import.meta.hot.accept` closure
|
|
212
|
-
// captured a module-scope variable — the closure and the constructor
|
|
213
|
-
// would then silently operate on two disconnected variable bindings
|
|
214
|
-
// (a duplicate-module symptom), and the HMR swap would never reach
|
|
215
|
-
// the instance actually rendered.
|
|
216
|
-
const ctorBody = babelTemplate.statements(`
|
|
217
|
-
super(...args);
|
|
218
|
-
this._owner = args[0];
|
|
219
|
-
const Impl = (import.meta.hot && import.meta.hot.data._impl) || ${proxyClassName}.Impl;
|
|
220
|
-
this._delegate = new Impl(this._owner);
|
|
221
|
-
if (import.meta.hot) {
|
|
222
|
-
import.meta.hot.data._proxy = this;
|
|
223
|
-
}
|
|
224
|
-
return new Proxy(this, {
|
|
225
|
-
get(target, prop) {
|
|
226
|
-
if (prop === '_delegate') {
|
|
227
|
-
return target._delegate;
|
|
228
|
-
}
|
|
229
|
-
return target._delegate[prop];
|
|
230
|
-
},
|
|
231
|
-
set(target, prop, value) {
|
|
232
|
-
target._delegate[prop] = value;
|
|
233
|
-
return true;
|
|
234
|
-
},
|
|
235
|
-
});
|
|
236
|
-
`)();
|
|
237
|
-
const willDestroyBody = babelTemplate.statements(`
|
|
238
|
-
super.willDestroy();
|
|
239
|
-
this._delegate.willDestroy();
|
|
240
|
-
if (import.meta.hot && import.meta.hot.data._proxy === this) {
|
|
241
|
-
import.meta.hot.data._proxy = undefined;
|
|
242
|
-
}
|
|
243
|
-
`)();
|
|
244
|
-
// Create the HMR proxy service class
|
|
245
|
-
const proxyClass = t.classDeclaration(t.identifier(proxyClassName), Service, t.classBody([
|
|
246
|
-
// static Impl = OriginalService (reference to the original class)
|
|
247
|
-
t.classProperty(t.identifier('Impl'), t.identifier(originalClassName), null, null, false, true),
|
|
248
|
-
// @tracked _delegate
|
|
249
|
-
t.classProperty(t.identifier('_delegate'), null, null, [t.decorator(tracked)], false, false),
|
|
250
|
-
t.classMethod('constructor', t.identifier('constructor'), [t.restElement(t.identifier('args'))], t.blockStatement(ctorBody)),
|
|
251
|
-
t.classMethod('method', t.identifier('willDestroy'), [], t.blockStatement(willDestroyBody)),
|
|
252
|
-
]));
|
|
253
|
-
// For Case 1 (inline class), we need to keep the class as non-exported
|
|
254
|
-
// For Case 2 (separate declaration), the class already exists, so we don't recreate it
|
|
255
|
-
if (declaration.type === 'ClassDeclaration') {
|
|
256
|
-
// Case 1: Inline class export - create a non-exported version
|
|
257
|
-
const originalClass = t.classDeclaration(classIdentifier, classDeclaration.superClass, classDeclaration.body, classDeclaration.decorators || []);
|
|
258
|
-
// Replace the export with all the necessary declarations
|
|
259
|
-
// IMPORTANT: Class must be declared BEFORE the proxy class that references it
|
|
260
|
-
path.replaceWithMultiple([
|
|
261
|
-
originalClass, // The original class (no longer exported) - MUST BE FIRST
|
|
262
|
-
t.exportDefaultDeclaration(proxyClass), // Export the proxy class
|
|
263
|
-
]);
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
// Case 2: Separate declaration - class already exists, just replace the export
|
|
267
|
-
path.replaceWithMultiple([
|
|
268
|
-
t.exportDefaultDeclaration(proxyClass), // Export the proxy class
|
|
269
|
-
]);
|
|
270
|
-
}
|
|
271
|
-
// Add HMR code after the export using babel template
|
|
272
|
-
if (programPath) {
|
|
273
|
-
const hmrCode = `
|
|
274
|
-
if (import.meta.hot) {
|
|
275
|
-
import.meta.hot.accept((newModule) => {
|
|
276
|
-
const NewImpl = newModule?.default?.Impl;
|
|
277
|
-
if (!NewImpl) {
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Remember the latest accepted implementation so a proxy
|
|
282
|
-
// constructed *after* this update (its instantiation raced
|
|
283
|
-
// behind the HMR swap) still picks up the new class instead
|
|
284
|
-
// of the stale one captured at module-evaluation time.
|
|
285
|
-
import.meta.hot.data._impl = NewImpl;
|
|
286
|
-
|
|
287
|
-
const proxy = import.meta.hot.data._proxy;
|
|
288
|
-
if (!proxy) {
|
|
289
|
-
// No instance has been created yet; the next construction
|
|
290
|
-
// will read import.meta.hot.data._impl above.
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const oldDelegate = proxy._delegate;
|
|
295
|
-
const newDelegate = new NewImpl(proxy._owner);
|
|
296
|
-
proxy._delegate = newDelegate;
|
|
297
|
-
|
|
298
|
-
// Sync state from old to new while keeping new implementation defaults
|
|
299
|
-
for (const key in oldDelegate) {
|
|
300
|
-
const descriptor =
|
|
301
|
-
Object.getOwnPropertyDescriptor(oldDelegate, key) ||
|
|
302
|
-
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(oldDelegate), key);
|
|
303
|
-
const hasOwnDefault = Object.prototype.hasOwnProperty.call(newDelegate, key);
|
|
304
|
-
const currentValue = newDelegate[key];
|
|
305
|
-
const previousValue = oldDelegate[key];
|
|
306
|
-
|
|
307
|
-
// Skip Service instances - they should not be synced
|
|
308
|
-
if (previousValue instanceof Service) {
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// Skip Function properties - they should not be synced
|
|
313
|
-
if (typeof previousValue === 'function') {
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const shouldSync =
|
|
318
|
-
!!descriptor &&
|
|
319
|
-
(descriptor.writable || descriptor.set || Object.prototype.hasOwnProperty.call(oldDelegate, key)) &&
|
|
320
|
-
(!hasOwnDefault || currentValue === previousValue);
|
|
321
|
-
|
|
322
|
-
if (shouldSync) {
|
|
323
|
-
try {
|
|
324
|
-
newDelegate[key] = previousValue;
|
|
325
|
-
} catch (e) {
|
|
326
|
-
// Skip non-writable properties
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
newDelegate._hmrAccepted?.(oldDelegate);
|
|
332
|
-
|
|
333
|
-
if (oldDelegate.willDestroy) {
|
|
334
|
-
oldDelegate.willDestroy();
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
`;
|
|
339
|
-
const template = babel.template.statements(hmrCode);
|
|
340
|
-
programPath.pushContainer('body', template());
|
|
341
|
-
}
|
|
54
|
+
renamePrivateClassMembers(babel, path, programPath);
|
|
342
55
|
},
|
|
343
|
-
|
|
56
|
+
ExportDefaultDeclaration(path, state) {
|
|
344
57
|
var _a;
|
|
345
58
|
if (process.env.EMBER_VITE_HMR_ENABLED !== 'true') {
|
|
346
59
|
return;
|
|
@@ -348,37 +61,17 @@ export default function hotReplaceAst(babel) {
|
|
|
348
61
|
if ((_a = state.filename) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
|
|
349
62
|
return;
|
|
350
63
|
}
|
|
351
|
-
|
|
352
|
-
|
|
64
|
+
transformServiceExport(babel, path, state);
|
|
65
|
+
},
|
|
66
|
+
Program(path, state) {
|
|
67
|
+
var _a;
|
|
68
|
+
if (process.env.EMBER_VITE_HMR_ENABLED !== 'true') {
|
|
353
69
|
return;
|
|
354
70
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
util.import(path, '@glimmer/component', 'default');
|
|
358
|
-
const klass = t.classExpression(path.scope.generateUidIdentifier('Imports'), null, t.classBody([]));
|
|
359
|
-
const bindings = [...hotAstProcessor.meta.importBindings].sort();
|
|
360
|
-
for (const local of bindings) {
|
|
361
|
-
klass.body.body.push(t.classProperty(t.identifier(local), t.identifier(local), null, [
|
|
362
|
-
t.decorator(tracked),
|
|
363
|
-
]));
|
|
71
|
+
if ((_a = state.filename) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
|
|
72
|
+
return;
|
|
364
73
|
}
|
|
365
|
-
|
|
366
|
-
const assign = t.assignmentExpression('=', t.identifier(hotAstProcessor.meta.importVar), newExp);
|
|
367
|
-
const varDeclaration = path.node.body.findIndex((e) => e.type === 'VariableDeclaration' &&
|
|
368
|
-
e.declarations[0].id.name ===
|
|
369
|
-
hotAstProcessor.meta.importVar) + 1;
|
|
370
|
-
const lastImportIndex = path.node.body.findLastIndex((e) => e.type === 'ImportDeclaration') + 1;
|
|
371
|
-
path.node.body.splice(Math.max(varDeclaration, lastImportIndex), 0, t.expressionStatement(assign));
|
|
372
|
-
// Export metadata about tracked imports for hmr.ts to use
|
|
373
|
-
const importMetadata = t.variableDeclaration('const', [
|
|
374
|
-
t.variableDeclarator(t.identifier('__hmr_import_metadata__'), t.objectExpression([
|
|
375
|
-
t.objectProperty(t.identifier('importVar'), t.stringLiteral(hotAstProcessor.meta.importVar)),
|
|
376
|
-
t.objectProperty(t.identifier('bindings'), t.arrayExpression(bindings.map((b) => t.stringLiteral(b)))),
|
|
377
|
-
])),
|
|
378
|
-
]);
|
|
379
|
-
const exportMetadata = t.exportNamedDeclaration(importMetadata, []);
|
|
380
|
-
path.node.body.push(exportMetadata);
|
|
381
|
-
path.scope.crawl();
|
|
74
|
+
finalizeTemplateImports(babel, path, state.filename);
|
|
382
75
|
},
|
|
383
76
|
},
|
|
384
77
|
};
|