| 1 | const { getRefreshGlobalScope } = require('../globals');
|
|---|
| 2 |
|
|---|
| 3 | /**
|
|---|
| 4 | * @typedef {Object} RuntimeTemplate
|
|---|
| 5 | * @property {function(string, string[]): string} basicFunction
|
|---|
| 6 | * @property {function(): boolean} supportsConst
|
|---|
| 7 | * @property {function(string, string=): string} returningFunction
|
|---|
| 8 | */
|
|---|
| 9 |
|
|---|
| 10 | /**
|
|---|
| 11 | * Generates the refresh global runtime template.
|
|---|
| 12 | * @param {import('webpack').Template} Template The template helpers.
|
|---|
| 13 | * @param {Record<string, string>} [RuntimeGlobals] The runtime globals.
|
|---|
| 14 | * @param {RuntimeTemplate} [RuntimeTemplate] The runtime template helpers.
|
|---|
| 15 | * @returns {string} The refresh global runtime template.
|
|---|
| 16 | */
|
|---|
| 17 | function getRefreshGlobal(
|
|---|
| 18 | Template,
|
|---|
| 19 | RuntimeGlobals = {},
|
|---|
| 20 | RuntimeTemplate = {
|
|---|
| 21 | basicFunction(args, body) {
|
|---|
| 22 | return `function(${args}) {\n${Template.indent(body)}\n}`;
|
|---|
| 23 | },
|
|---|
| 24 | supportsConst() {
|
|---|
| 25 | return false;
|
|---|
| 26 | },
|
|---|
| 27 | returningFunction(returnValue, args = '') {
|
|---|
| 28 | return `function(${args}) { return ${returnValue}; }`;
|
|---|
| 29 | },
|
|---|
| 30 | }
|
|---|
| 31 | ) {
|
|---|
| 32 | const declaration = RuntimeTemplate.supportsConst() ? 'const' : 'var';
|
|---|
| 33 | const refreshGlobal = getRefreshGlobalScope(RuntimeGlobals);
|
|---|
| 34 | return Template.asString([
|
|---|
| 35 | `${refreshGlobal} = {`,
|
|---|
| 36 | Template.indent([
|
|---|
| 37 | // Lifecycle methods - They should be specific per module and restored after module execution.
|
|---|
| 38 | // These stubs ensure unwanted calls (e.g. unsupported patterns, broken transform) would not error out.
|
|---|
| 39 | // If the current module is processed by our loader,
|
|---|
| 40 | // they will be swapped in place during module initialisation by the `setup` method below.
|
|---|
| 41 | `register: ${RuntimeTemplate.returningFunction('undefined')},`,
|
|---|
| 42 | `signature: ${RuntimeTemplate.returningFunction(
|
|---|
| 43 | RuntimeTemplate.returningFunction('type', 'type')
|
|---|
| 44 | )},`,
|
|---|
| 45 | // Runtime - This should be a singleton and persist throughout the lifetime of the app.
|
|---|
| 46 | // This stub ensures calls to `runtime` would not error out.
|
|---|
| 47 | // If any module within the bundle is processed by our loader,
|
|---|
| 48 | // it will be swapped in place via an injected import.
|
|---|
| 49 | 'runtime: {',
|
|---|
| 50 | Template.indent([
|
|---|
| 51 | `createSignatureFunctionForTransform: ${RuntimeTemplate.returningFunction(
|
|---|
| 52 | RuntimeTemplate.returningFunction('type', 'type')
|
|---|
| 53 | )},`,
|
|---|
| 54 | `register: ${RuntimeTemplate.returningFunction('undefined')}`,
|
|---|
| 55 | ]),
|
|---|
| 56 | '},',
|
|---|
| 57 | // Setup - This handles initialisation of the global runtime.
|
|---|
| 58 | // It should never be touched throughout the lifetime of the app.
|
|---|
| 59 | `setup: ${RuntimeTemplate.basicFunction('currentModuleId', [
|
|---|
| 60 | // Store all previous values for fields on `refreshGlobal` -
|
|---|
| 61 | // this allows proper restoration in the `cleanup` phase.
|
|---|
| 62 | `${declaration} prevModuleId = ${refreshGlobal}.moduleId;`,
|
|---|
| 63 | `${declaration} prevRegister = ${refreshGlobal}.register;`,
|
|---|
| 64 | `${declaration} prevSignature = ${refreshGlobal}.signature;`,
|
|---|
| 65 | `${declaration} prevCleanup = ${refreshGlobal}.cleanup;`,
|
|---|
| 66 | '',
|
|---|
| 67 | `${refreshGlobal}.moduleId = currentModuleId;`,
|
|---|
| 68 | '',
|
|---|
| 69 | `${refreshGlobal}.register = ${RuntimeTemplate.basicFunction('type, id', [
|
|---|
| 70 | `${declaration} typeId = currentModuleId + " " + id;`,
|
|---|
| 71 | `${refreshGlobal}.runtime.register(type, typeId);`,
|
|---|
| 72 | ])}`,
|
|---|
| 73 | '',
|
|---|
| 74 | `${refreshGlobal}.signature = ${RuntimeTemplate.returningFunction(
|
|---|
| 75 | `${refreshGlobal}.runtime.createSignatureFunctionForTransform()`
|
|---|
| 76 | )};`,
|
|---|
| 77 | '',
|
|---|
| 78 | `${refreshGlobal}.cleanup = ${RuntimeTemplate.basicFunction('cleanupModuleId', [
|
|---|
| 79 | // Only cleanup if the module IDs match.
|
|---|
| 80 | // In rare cases, it might get called in another module's `cleanup` phase.
|
|---|
| 81 | 'if (currentModuleId === cleanupModuleId) {',
|
|---|
| 82 | Template.indent([
|
|---|
| 83 | `${refreshGlobal}.moduleId = prevModuleId;`,
|
|---|
| 84 | `${refreshGlobal}.register = prevRegister;`,
|
|---|
| 85 | `${refreshGlobal}.signature = prevSignature;`,
|
|---|
| 86 | `${refreshGlobal}.cleanup = prevCleanup;`,
|
|---|
| 87 | ]),
|
|---|
| 88 | '}',
|
|---|
| 89 | ])}`,
|
|---|
| 90 | ])}`,
|
|---|
| 91 | ]),
|
|---|
| 92 | '};',
|
|---|
| 93 | ]);
|
|---|
| 94 | }
|
|---|
| 95 |
|
|---|
| 96 | module.exports = getRefreshGlobal;
|
|---|