@komaci/esm-generator 242.0.0 → 242.1.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.
Files changed (41) hide show
  1. package/build/__tests__/adgAstGeneration.spec.d.ts +2 -0
  2. package/build/__tests__/adgAstGeneration.spec.js +31 -0
  3. package/build/__tests__/compositionAstGeneration.spec.d.ts +2 -0
  4. package/build/__tests__/compositionAstGeneration.spec.js +394 -0
  5. package/build/__tests__/functionAstGeneration.spec.d.ts +2 -0
  6. package/build/__tests__/functionAstGeneration.spec.js +412 -0
  7. package/build/__tests__/general-komaci-docs/template-component/source.js +3 -3
  8. package/build/__tests__/genericAstGeneration.spec.d.ts +2 -0
  9. package/build/__tests__/genericAstGeneration.spec.js +586 -0
  10. package/build/__tests__/index.spec.js +8 -8
  11. package/build/__tests__/komaci-ast-unit.spec.js +240 -448
  12. package/build/__tests__/komaci-bundle-module.fixtures.spec.js +1 -0
  13. package/build/__tests__/komaci-script-module.fixtures.spec.js +5 -1
  14. package/build/__tests__/komaci-template-module.fixtures.spec.js +2 -1
  15. package/build/componentAstProcessing.d.ts +34 -0
  16. package/build/componentAstProcessing.js +105 -0
  17. package/build/compositionAstGeneration.d.ts +76 -0
  18. package/build/compositionAstGeneration.js +299 -0
  19. package/build/functionAstGeneration.d.ts +81 -0
  20. package/build/functionAstGeneration.js +337 -0
  21. package/build/genericAstGeneration.d.ts +107 -0
  22. package/build/genericAstGeneration.js +600 -0
  23. package/build/index.d.ts +2 -3
  24. package/build/index.js +19 -36
  25. package/build/types.d.ts +13 -2
  26. package/build/types.js +69 -1
  27. package/package.json +4 -4
  28. package/build/__tests__/modGenScript.spec.d.ts +0 -2
  29. package/build/__tests__/modGenScript.spec.js +0 -110
  30. package/build/__tests__/modGenTemplate.spec.d.ts +0 -2
  31. package/build/__tests__/modGenTemplate.spec.js +0 -196
  32. package/build/__tests__/shared.spec.d.ts +0 -2
  33. package/build/__tests__/shared.spec.js +0 -66
  34. package/build/__tests__/templateStrings.spec.d.ts +0 -2
  35. package/build/__tests__/templateStrings.spec.js +0 -130
  36. package/build/modGenScript.d.ts +0 -38
  37. package/build/modGenScript.js +0 -1031
  38. package/build/modGenTemplate.d.ts +0 -37
  39. package/build/modGenTemplate.js +0 -406
  40. package/build/shared.d.ts +0 -149
  41. package/build/shared.js +0 -480
package/build/shared.js DELETED
@@ -1,480 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.sanitizeFunction = exports.mapRealNameToGenerated = exports.hoistTemplateStrings = exports.processTemplateStrings = exports.transformGetters = exports.processGetters = exports.getComponentSrcJs = exports.valueToExpression = exports.bindingRootToExpression = exports.bindingToExpression = exports.primitiveToExpression = exports.getFactoryFuncDeclaration = exports.retrieveImportInfo = exports.updateImportInfoState = exports.ID = exports.PRIMING_FUNCTION = exports.ERROR_FUNCTION = exports.GETTER_FUNCTION = exports.WIRE_FUNCTION = exports.USER_VARIABLE_PREFIX = exports.UNRESOLVED = exports.ADG_IMPORT_SUFFIX = exports.PROPS = exports.CONTEXT = exports.ERROR_PREFIX = void 0;
27
- const t = __importStar(require("@babel/types"));
28
- const types_1 = require("./types");
29
- const static_analyzer_1 = require("@komaci/static-analyzer");
30
- const common_shared_1 = require("@komaci/common-shared");
31
- exports.ERROR_PREFIX = '[komaci esm-generator] ';
32
- exports.CONTEXT = 'ctx';
33
- exports.PROPS = 'props';
34
- exports.ADG_IMPORT_SUFFIX = 'getAdgDefinition';
35
- exports.UNRESOLVED = 'unresolved';
36
- exports.USER_VARIABLE_PREFIX = 'user_var_';
37
- exports.WIRE_FUNCTION = 'WireFunction';
38
- exports.GETTER_FUNCTION = 'GetterFunction';
39
- exports.ERROR_FUNCTION = 'ErrorFunction';
40
- exports.PRIMING_FUNCTION = 'PrimingFunction';
41
- exports.ID = {
42
- CONTEXT: t.identifier(exports.CONTEXT),
43
- PROPS: t.identifier(exports.PROPS),
44
- FACTORY: t.identifier('fct'),
45
- COMPOSED_GRAPH_FUNC: t.identifier('cg'),
46
- ITERATION_FUNC: t.identifier('i'),
47
- UNRESOLVED_FUNC: t.identifier('u'),
48
- SLOT_FUNC: t.identifier('s'),
49
- ELEMENT_FUNC: t.identifier('e'),
50
- ADG_FUNC: t.identifier('adg'),
51
- SLOT: t.identifier('slot'),
52
- COMPONENT_ID: t.identifier('componentId'),
53
- UNDEFINED: t.identifier('undefined'),
54
- PROP_API: t.identifier('a'),
55
- PROP_INIT: t.identifier('i'),
56
- PROP_FUNC: t.identifier('f'),
57
- PROP_GETTER: t.identifier('g'),
58
- DEFAULT_COMP: t.identifier('comp1'),
59
- FUNC_ID: t.identifier('f'),
60
- FUNC_NAME: t.identifier('fN'),
61
- FUNC_TYPE: t.identifier('t'),
62
- FUNC_CONFIG: t.identifier('c'),
63
- FUNC_INPUT: t.identifier('in'),
64
- WIRE_TYPE: t.identifier('wt'),
65
- UNRESOLVED_VALUE: t.identifier('unresolved'),
66
- BATCH_FUNC_ID: t.identifier('b'),
67
- BATCH_FUNC_NAME: t.identifier('bN'),
68
- REDUCER_FUNC_ID: t.identifier('r'),
69
- IMG_SRC: t.identifier('src'),
70
- IMG_FUNC: t.identifier('img'),
71
- };
72
- /**
73
- * Retrieve info about an import given its reference value (e.g. 0/names/0), while initializing/updating its usageState, as well
74
- * as updating required factory functions (if we are returning an ImportInfo for an unsupported namespace).
75
- * @param generatorState the GeneratorState
76
- * @param importRefValue import reference value, as a string. ex: "0/names/0"
77
- * @param isScriptFile boolean indicating whether we are calling the method while processing a Script (JS file)[true], or a template (HTML file)[false]
78
- * @param usageState ImportUsageState enum that represents the way the import will be used. Some example values are: composedadg, wireadapter,
79
- * getter, initialvalue, wireconfig, parentadg
80
- * @returns ImportInfo object, updated with latest usageState
81
- */
82
- function updateImportInfoState(generatorState, importRefValue, isScriptFile, usageState) {
83
- const importInfo = isScriptFile
84
- ? generatorState.scriptGenState.importRefsMap[importRefValue]
85
- : generatorState.templateGenState.importRefsMap[importRefValue];
86
- if (!importInfo) {
87
- throw new Error(exports.ERROR_PREFIX + 'komaciDoc contains invalid import reference');
88
- }
89
- if (isScriptFile) {
90
- importInfo.importUsages.add(usageState);
91
- if (usageState === types_1.ImportUsageState.wireadapter) {
92
- generatorState.scriptGenState.importInfosForWireAdapter.add(importInfo);
93
- }
94
- if (!(0, static_analyzer_1.isSupportedNamespace)(importInfo.resourceName)) {
95
- generatorState.scriptGenState.requiredFactoryFunctions.add(exports.ID.UNRESOLVED_VALUE);
96
- }
97
- }
98
- return importInfo;
99
- }
100
- exports.updateImportInfoState = updateImportInfoState;
101
- /**
102
- * Retrieve info about an import given its reference value (e.g. 0/names/0), without updating its state.
103
- * To update ImportInfo state, see method updateImportInfoState.
104
- * @param generatorState the current GeneratorState for this module generation
105
- * @param importRefValue the import reference value to use in looking up the ImportInfo. ex: "0/names/0"
106
- * @param isScriptFile boolean determining whether we are processing a script (JS) or template (HTML)
107
- * @returns ImportInfo corresponding to the importRefValue in the generatorState
108
- */
109
- function retrieveImportInfo(generatorState, importRefValue, isScriptFile) {
110
- return isScriptFile
111
- ? generatorState.scriptGenState.importRefsMap[importRefValue]
112
- : generatorState.templateGenState.importRefsMap[importRefValue];
113
- }
114
- exports.retrieveImportInfo = retrieveImportInfo;
115
- // Return the variable declaration done via destructuring the factory object
116
- // (e.g. const { i, cg } = fct;) or undefined if no fct functions are used.
117
- function getFactoryFuncDeclaration(generatorState, isScriptFile) {
118
- const fctFunctions = [];
119
- const requiredFactoryFunctionsSet = isScriptFile
120
- ? generatorState.scriptGenState.requiredFactoryFunctions
121
- : generatorState.templateGenState.requiredFactoryFunctions;
122
- // Only functions which are used within the module are actually assigned.
123
- requiredFactoryFunctionsSet.forEach((funcId) => {
124
- fctFunctions.push(t.objectProperty(funcId, funcId, false, true));
125
- });
126
- if (fctFunctions.length) {
127
- const declarator = t.variableDeclarator(t.objectPattern(fctFunctions), exports.ID.FACTORY);
128
- return t.variableDeclaration('const', [declarator]);
129
- }
130
- }
131
- exports.getFactoryFuncDeclaration = getFactoryFuncDeclaration;
132
- // Convert a Komaci primitive value to babel expression.
133
- function primitiveToExpression(generatorState, primitive) {
134
- switch (typeof primitive.value) {
135
- case 'number':
136
- return t.numericLiteral(primitive.value);
137
- case 'string':
138
- return t.stringLiteral(primitive.value);
139
- case 'boolean':
140
- return t.booleanLiteral(primitive.value);
141
- case 'undefined':
142
- return exports.ID.UNDEFINED;
143
- default:
144
- return t.nullLiteral();
145
- }
146
- }
147
- exports.primitiveToExpression = primitiveToExpression;
148
- // Convert binding (or PropertyReference) to a babel expr (e.g. record.value?.Id).
149
- function bindingToExpression(generatorState, binding, isScriptFile) {
150
- if (!binding.value.length) {
151
- if (binding.type === 'Binding') {
152
- throw new Error(exports.ERROR_PREFIX + 'encountered empty binding');
153
- }
154
- throw new Error(exports.ERROR_PREFIX + 'encountered empty property reference');
155
- }
156
- const segments = binding.value.split('/'); // segments[0] === propertyName
157
- let chainingStartIdx;
158
- let iteratorBinding = false;
159
- // Am I in the context of an iteration?
160
- if (generatorState.iterationContext.includes(segments[0])) {
161
- // Referencing property of an iteration
162
- iteratorBinding = true; // flag to distinguish whether we are in the context of an iteration
163
- chainingStartIdx = 1;
164
- }
165
- else {
166
- // Not referencing property of an iteration
167
- // Are we referencing a property in the adg of the associated composition? Add to Set of reference properties on reaching this else
168
- if (!isScriptFile) {
169
- // put property into the Set of strings, and later convert into an array of stringLiterals later for arg 4
170
- generatorState.templateGenState.refProps.add(segments[0]);
171
- }
172
- chainingStartIdx = 2;
173
- segments.unshift(exports.CONTEXT, exports.PROPS); // Referencing property in context, so prepend ctx.props
174
- }
175
- // Build member expression w/ optional chaining to prevent runtime TypeError.
176
- // If we are in the context of an iterator binding, we must prepend the user variable prefix
177
- let expr = iteratorBinding
178
- ? t.identifier(exports.USER_VARIABLE_PREFIX + segments[0])
179
- : t.identifier(segments[0]);
180
- for (let i = 1; i < segments.length; ++i) {
181
- expr = t.optionalMemberExpression(expr, t.identifier(segments[i]), false, i > chainingStartIdx);
182
- }
183
- return expr;
184
- }
185
- exports.bindingToExpression = bindingToExpression;
186
- // Convert binding root (or PropertyReference) to a babel expr (e.g. ctx.prop.record).
187
- function bindingRootToExpression(generatorState, binding) {
188
- if (!binding.value.length) {
189
- if (binding.type === 'Binding') {
190
- throw new Error(exports.ERROR_PREFIX + 'encountered empty binding');
191
- }
192
- throw new Error(exports.ERROR_PREFIX + 'encountered empty property reference');
193
- }
194
- const segments = binding.value.split('/').slice(0, 1);
195
- let iterationBinding = false;
196
- // not referencing property of an iteration.
197
- if (!generatorState.iterationContext.includes(segments[0])) {
198
- // Referencing property in context, so prepend ctx.props
199
- segments.unshift(exports.CONTEXT, exports.PROPS);
200
- }
201
- else {
202
- iterationBinding = true; // we are referencing a property of an iteration
203
- }
204
- // Build member expression w/ optional chaining to prevent runtime TypeError.
205
- // if we are in the context of an iteration, prepend the user variable prefix
206
- let expr = iterationBinding
207
- ? t.identifier(exports.USER_VARIABLE_PREFIX + segments[0])
208
- : t.identifier(segments[0]);
209
- for (let i = 1; i < segments.length; ++i) {
210
- expr = t.memberExpression(expr, t.identifier(segments[i]), false);
211
- }
212
- return expr;
213
- }
214
- exports.bindingRootToExpression = bindingRootToExpression;
215
- // Convert any possible value within a Komaci ADG to a babel expression.
216
- function valueToExpression(generatorState, komaciValue, isScriptFile, usageState) {
217
- let newExpression;
218
- switch (komaciValue.type) {
219
- case 'PrimitiveValue':
220
- newExpression = primitiveToExpression(generatorState, komaciValue);
221
- break;
222
- case 'ImportReference': {
223
- const importInfo = updateImportInfoState(
224
- // called from a lot of different places. Add a way to indicate where getImportInfo is being used.
225
- generatorState, komaciValue.value, isScriptFile, usageState);
226
- newExpression = importInfo.localName;
227
- if (newExpression?.name !== exports.UNRESOLVED && komaciValue.namespacedMember) {
228
- newExpression = t.memberExpression(newExpression, t.identifier(komaciValue.namespacedMember));
229
- }
230
- break;
231
- }
232
- case 'PropertyReference': {
233
- return bindingToExpression(generatorState, komaciValue, isScriptFile);
234
- }
235
- case 'Binding': {
236
- const objProps = [];
237
- objProps.push(t.objectProperty(t.stringLiteral('url'), bindingToExpression(generatorState, komaciValue, isScriptFile)));
238
- return t.objectExpression(objProps);
239
- }
240
- case 'Unresolved':
241
- isScriptFile
242
- ? generatorState.scriptGenState.requiredFactoryFunctions.add(exports.ID.UNRESOLVED_VALUE)
243
- : generatorState.templateGenState.requiredFactoryFunctions.add(exports.ID.UNRESOLVED_VALUE);
244
- newExpression = exports.ID.UNRESOLVED_VALUE;
245
- break;
246
- case 'ArrayValue': {
247
- const elements = [];
248
- komaciValue.value.forEach((element) => {
249
- elements.push(valueToExpression(generatorState, element, isScriptFile, usageState));
250
- });
251
- newExpression = t.arrayExpression(elements);
252
- break;
253
- }
254
- case 'ObjectValue': {
255
- const objProps = [];
256
- for (const [propName, propValue] of Object.entries(komaciValue.value)) {
257
- objProps.push(t.objectProperty(t.stringLiteral(propName), valueToExpression(generatorState, propValue, isScriptFile, usageState)));
258
- }
259
- newExpression = t.objectExpression(objProps);
260
- break;
261
- }
262
- }
263
- if (!newExpression) {
264
- throw new Error(`${exports.ERROR_PREFIX}: Unrecognized value type`);
265
- }
266
- return newExpression;
267
- }
268
- exports.valueToExpression = valueToExpression;
269
- /**
270
- * Retrieve the file path for the js of a component
271
- * @param generatorState GeneratorState containg the GeneratorInput, which in turn contains the JS raw source file
272
- * @returns Returns raw source code as string for the js of a component if it exists in the srcFileMap
273
- * Returns undefined if no JS source file (whose filename also matches the LWC module name) was included in the
274
- * GeneratorState.GeneratorInput by lwc-platform, other calling code.
275
- */
276
- function getComponentSrcJs(generatorState) {
277
- let sourceCode;
278
- const moduleName = generatorState.input.moduleInfo.name;
279
- if (generatorState.input.srcFileMap) {
280
- const filename = Object.keys(generatorState.input.srcFileMap).find((filename) => filename.endsWith('.js') && filename.startsWith(moduleName));
281
- if (filename) {
282
- sourceCode = generatorState.input.srcFileMap[filename];
283
- }
284
- }
285
- return sourceCode;
286
- }
287
- exports.getComponentSrcJs = getComponentSrcJs;
288
- /**
289
- * AST is traversed to see if they contain getter functions that are not valid. For each getter that is valid, we will
290
- * update contextual information about the class and pass back info about the valid getters.
291
- *
292
- * @param {ClassPropertyContexts} properties the Map of properties metadata, which tells whether a property is used by a wire functions
293
- * @param {ModuleContext} moduleContext Contextual info about the module itself
294
- * @param {ModuleLevelConsumption} moduleLevelConsumption Details about how things are consuming module level entities. NOTE: This is updated in here for import usage
295
- * @param {t.File} ast The ast for the module
296
- * @returns Information about valid getters to be added to the resolvable Module.
297
- */
298
- function processGetters(properties, moduleContext, moduleLevelConsumption, getterMethodPaths) {
299
- return (getterMethodPaths
300
- // filter removes invalid getters from the array
301
- .filter((getter) => (0, static_analyzer_1.validateGetter)(getter, moduleContext, false))
302
- // map changes the item at each index to be an instance of ValidGetterContext
303
- .map((getter, index) => {
304
- const { identifiers } = (0, common_shared_1.implicitConsumptionMetadata)(getter, moduleContext.astContext.classProperties, // info on all class properties
305
- moduleContext.astContext.importDeclarations, // import metadata info
306
- moduleLevelConsumption);
307
- if (identifiers.length > 0) {
308
- identifiers.forEach((identifier) => {
309
- properties.get(identifier);
310
- });
311
- }
312
- return {
313
- getter,
314
- generatedName: `g${index}`,
315
- memberUsage: identifiers,
316
- };
317
- })
318
- .map((getter) => {
319
- (0, common_shared_1.updatePropertyUsage)((0, common_shared_1.getClassMethodName)(getter.getter), getter.memberUsage, properties, common_shared_1.PropertyTypes.GETTER);
320
- return getter;
321
- }));
322
- }
323
- exports.processGetters = processGetters;
324
- /**
325
- * This method takes in the generatedCombinedModule AST, the original source AST, the import references map from the
326
- * GeneratorState, and the valid getter contexts (which contain the babel NodePaths to the getters) and transforms the generated
327
- * combined module AST by hoisting any passed-in valid getters into top-level getter methods, adding `props` as input paramater to the
328
- * same getter methods, replacing this.<var> references in the getter method to props.<var>, as well as replacing references of
329
- * valid imports references in the getter with corresponding Komaci module unique identifiers (i1, i2, i3,...).
330
- *
331
- * @param genCombinedModuleAST the AST of the generated combined module
332
- * @param importReferencesMap Map of importReferences (ex: "0/names/0") to ImportInfo, which comes from GeneratorState's scriptGenState.importRefsMap
333
- * @param getterImportUsage All the imports decalred in the ast
334
- * @param validGetterContexts Array of ValidGetterContext object which contain the NodePath representing the getter, as well as an Array<string> of
335
- * memberUsages within the same getter.
336
- */
337
- function transformGetters(genCombinedModuleAST, importReferencesMap, getterImportUsage, validGetterContexts) {
338
- const trueToGeneratedImport = mapRealNameToGenerated(importReferencesMap);
339
- let body = [];
340
- const hoistedGetters = [];
341
- for (const getterCtx of validGetterContexts) {
342
- sanitizeFunction(getterCtx.getter, getterImportUsage, trueToGeneratedImport);
343
- // hoist getters to module-level
344
- // use direct-access here since it is possible for this portion
345
- const program = genCombinedModuleAST.program;
346
- body = program.body;
347
- const propsId = t.identifier(exports.PROPS);
348
- const hoistedGetter = t.functionDeclaration(t.identifier(getterCtx.generatedName), [propsId], // make 'props' an input parameter to the hoisted getter
349
- getterCtx.getter.node.body);
350
- hoistedGetters.push(hoistedGetter);
351
- }
352
- // add hoisted getter functions in the array of Statements for the program body, in the first spot after
353
- // all of the ImportDeclarations
354
- const insertBeforeIndex = body.findIndex((statement) => statement.type !== 'ImportDeclaration');
355
- body.splice(insertBeforeIndex, 0, ...hoistedGetters);
356
- }
357
- exports.transformGetters = transformGetters;
358
- /**
359
- * Validate what templates are good and then uplift the metadata about how they interact with other portions of the modules.
360
- * i.e. import, property references, used in priming
361
- * @param {ClassPropertyContexts} properties the Map of properties metadata, which tells whether a property is used by a wire functions
362
- * @param {ModuleContext} moduleContext Contextual info about the module itself
363
- * @param {ModuleLevelConsumption} moduleLevelConsumption Details about how things are consuming module level entities. NOTE: This is updated in here for import usage
364
- * @param {Array<NodePath<t.ClassProperty>>} templateStrings The templates to validate
365
- * @returns Information about valid templates to be added to the resolvable Module.
366
- */
367
- function processTemplateStrings(properties, moduleContext, moduleLevelConsumption, templateStrings) {
368
- return templateStrings
369
- .filter((template) => (0, static_analyzer_1.validateTemplateString)(template, moduleContext, false))
370
- .map((template, index) => {
371
- const { identifiers } = (0, common_shared_1.implicitConsumptionMetadata)(template, moduleContext.astContext.classProperties, // info on all class properties
372
- moduleContext.astContext.importDeclarations, // import metadata info
373
- moduleLevelConsumption);
374
- return {
375
- template,
376
- generatedName: `t${index}`,
377
- memberUsage: identifiers,
378
- };
379
- })
380
- .map((template) => {
381
- (0, common_shared_1.updatePropertyUsage)((0, common_shared_1.getFromIdentifierOrStringLiteral)(template.template.node.key), template.memberUsage, properties, common_shared_1.PropertyTypes.TEMPLATE_STRING);
382
- return template;
383
- });
384
- }
385
- exports.processTemplateStrings = processTemplateStrings;
386
- /**
387
- * Converts templates into single line functions, hoisted to the top level of the resolvable module.
388
- * Part of this hoisting is going through and updating references to properties or imports. similar to what we do for getters.
389
- *
390
- * @param genCombinedModuleAST the AST of the generated combined module
391
- * @param importReferencesMap Map of importReferences (ex: "0/names/0") to ImportInfo, which comes from GeneratorState's scriptGenState.importRefsMap
392
- * @param definedImports All the imports decalred in the ast
393
- * @param validGetterContexts Array of valid templates
394
- */
395
- function hoistTemplateStrings(genCombinedModuleAST, importReferencesMap, definedImports, templateStrings) {
396
- const trueToGeneratedImport = mapRealNameToGenerated(importReferencesMap);
397
- let body = [];
398
- const hoistedTemplateStrings = [];
399
- for (const templateString of templateStrings) {
400
- sanitizeFunction(templateString.template, definedImports, trueToGeneratedImport);
401
- const program = genCombinedModuleAST.program;
402
- body = program.body;
403
- const propsId = t.identifier(exports.PROPS);
404
- const hoistedGetter = t.functionDeclaration(t.identifier(templateString.generatedName), [propsId], t.blockStatement([t.returnStatement(templateString.template.node.value)]));
405
- hoistedTemplateStrings.push(hoistedGetter);
406
- }
407
- const insertBeforeIndex = body.findIndex((statement) => statement.type !== 'ImportDeclaration');
408
- body.splice(insertBeforeIndex, 0, ...hoistedTemplateStrings);
409
- }
410
- exports.hoistTemplateStrings = hoistTemplateStrings;
411
- /**
412
- * Create a mapping from the original name of an import to the generated one made by komaci
413
- * @param importReferencesMap The inverse mapping of generated name to info
414
- * @returns A map of original import name to generated name
415
- */
416
- function mapRealNameToGenerated(importReferencesMap) {
417
- const trueToGeneratedImport = new Map();
418
- for (const ref of Object.values(importReferencesMap)) {
419
- if (ref.importSpecifier.type === 'ImportDefaultSpecifier' ||
420
- ref.importSpecifier.type === 'ImportNamespaceSpecifier') {
421
- trueToGeneratedImport.set(ref.resourceName, ref.localName.name);
422
- }
423
- else {
424
- trueToGeneratedImport.set((0, common_shared_1.getFromIdentifierOrStringLiteral)(ref.importSpecifier.imported), ref.localName.name);
425
- }
426
- }
427
- return trueToGeneratedImport;
428
- }
429
- exports.mapRealNameToGenerated = mapRealNameToGenerated;
430
- /**
431
- * Take a function defined on a class and sanitize it's interactions in preparation to be hoisted into resolvable module/
432
- *
433
- * Two main things happen during sanitization:
434
- * - references to imports are updated to their generated name (i.e. i2)
435
- * - references to `this` are replaced with references to `props`
436
- *
437
- * @param nodePath The node to sanitize
438
- * @param definedImports Metadata about all the imports we know about
439
- * @param trueToGeneratedImport Mapping of real import name to generated name
440
- */
441
- function sanitizeFunction(nodePath, definedImports, trueToGeneratedImport) {
442
- const Visitors = {
443
- Identifier(path) {
444
- if ((path.parent.type === 'MemberExpression' &&
445
- path.parent.property === path.node) ||
446
- path.parent.type === 'Decorator') {
447
- //when a property shares a same name with an import,
448
- //it will be identified as an import
449
- //this check skips the scenario
450
- return;
451
- }
452
- const info = definedImports.get(path.node.name);
453
- let localName;
454
- if (info && (info.isDefault || info.isNamespaceSpecifier)) {
455
- localName = trueToGeneratedImport.get(info.namespace);
456
- }
457
- else if (info && info.trueName) {
458
- localName = trueToGeneratedImport.get(info.trueName);
459
- }
460
- else if (info) {
461
- localName = trueToGeneratedImport.get(info.identifierName);
462
- }
463
- if (localName && localName !== exports.UNRESOLVED) {
464
- path.replaceWith(t.identifier(localName)); // replace usage of import specifier in getter
465
- }
466
- else if (localName === exports.UNRESOLVED) {
467
- // legit this should never happen but if we somehow missed an edge case somewhere this will prevent a malformed module from going out
468
- throw new Error(`${exports.ERROR_PREFIX}: '${path.node.name}' does not map to valid import`);
469
- }
470
- },
471
- MemberExpression(path) {
472
- if (path.node.object.type === 'ThisExpression') {
473
- path.replaceWith(t.memberExpression(t.identifier(exports.PROPS), path.node.property)); // replace this.<var> with props.<var>
474
- }
475
- },
476
- };
477
- nodePath.traverse(Visitors);
478
- }
479
- exports.sanitizeFunction = sanitizeFunction;
480
- //# sourceMappingURL=shared.js.map