rollup-plugin-concurrent-top-level-await 0.0.9 → 0.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.
- package/README.md +10 -1
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +47 -49
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,16 @@ export default {
|
|
|
30
30
|
};
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
## Options
|
|
34
|
+
|
|
35
|
+
| Option | Type | Default | Description |
|
|
36
|
+
| ------------------------- | --------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `include` | `FilterPattern` | `undefined` | A pattern specifying which files to include. See [below](#which-modules-to-include) to determine which modules to include. |
|
|
38
|
+
| `exclude` | `FilterPattern` | `undefined` | A pattern specifying which files to exclude. Must still follow the [same considerations](#which-modules-to-include) as `include`. |
|
|
39
|
+
| `sourceMap` | `boolean` | `true` | Whether to generate source maps for transformed files. |
|
|
40
|
+
| `generatedVariablePrefix` | `string` | `"__tla"` | Prefix used for internal variables generated by the plugin. Change this if it conflicts with variable names in your code. |
|
|
41
|
+
|
|
42
|
+
### Which modules to include?
|
|
34
43
|
|
|
35
44
|
The plugin needs to handle not only modules that directly contain a top-level `await`, but also their ancestor modules up to the lowest common ancestor. Ancestor modules must be transformed to handle the asynchronous completion of their children concurrently. As an example, consider the following module structure:
|
|
36
45
|
|
package/dist/index.d.mts
CHANGED
|
@@ -7,6 +7,12 @@ declare function concurrentTopLevelAwait(options?: {
|
|
|
7
7
|
include?: FilterPattern;
|
|
8
8
|
exclude?: FilterPattern;
|
|
9
9
|
sourceMap?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Prefix used for internal variables generated by the plugin.
|
|
12
|
+
* Change this if it conflicts with variable names in your code.
|
|
13
|
+
* @default "__tla"
|
|
14
|
+
*/
|
|
15
|
+
generatedVariablePrefix?: string;
|
|
10
16
|
}): {
|
|
11
17
|
name: string;
|
|
12
18
|
apply: "build";
|
package/dist/index.mjs
CHANGED
|
@@ -128,63 +128,61 @@ var AsyncModuleTracker = class {
|
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region src/transform.ts
|
|
131
|
-
function transform(s, ast, asyncImports, hasAwait) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
s
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
s = s.append("if (import.meta.useTla) await __todo;");
|
|
152
|
-
s = s.append("export function __tla_access() { return __tla; };");
|
|
153
|
-
return s;
|
|
131
|
+
function transform(s, ast, asyncImports, hasAwait, variablePrefix) {
|
|
132
|
+
const declarationsEnd = tansformAndMoveDeclarationsToModuleScope(s, ast, asyncImports, variablePrefix);
|
|
133
|
+
s.appendRight(declarationsEnd, `async function ${variablePrefix}_initModuleExports() {\n`);
|
|
134
|
+
s.append("\n}\n");
|
|
135
|
+
const asyncDeps = `[${asyncImports.map((_, i) => `${variablePrefix}${i}`).join()}].flatMap(a => {
|
|
136
|
+
try {
|
|
137
|
+
const result = a();
|
|
138
|
+
if (Array.isArray(result)) {
|
|
139
|
+
return result
|
|
140
|
+
}
|
|
141
|
+
return [a];
|
|
142
|
+
} catch {
|
|
143
|
+
return []; // happens for cyclic dependencies
|
|
144
|
+
}
|
|
145
|
+
})`;
|
|
146
|
+
const initModuleExportsAfterDeps = asyncImports.length === 0 ? `${variablePrefix}_initModuleExports()` : `Promise.all(${asyncDeps}.map(e => e())).then(() => ${variablePrefix}_initModuleExports())`;
|
|
147
|
+
if (hasAwait) s.append(`const ${variablePrefix} = ${initModuleExportsAfterDeps};\nconst ${variablePrefix}_initPromise = ${variablePrefix};\n`);
|
|
148
|
+
else s.append(`const ${variablePrefix} = ${asyncDeps};\nconst ${variablePrefix}_initPromise = ${initModuleExportsAfterDeps};\n`);
|
|
149
|
+
s.append(`if (import.meta.useTla) await ${variablePrefix}_initPromise;\n`);
|
|
150
|
+
s.append(`export function ${variablePrefix}_access() { return ${variablePrefix}; };\n`);
|
|
154
151
|
}
|
|
155
|
-
function tansformAndMoveDeclarationsToModuleScope(s, ast, asyncImports) {
|
|
152
|
+
function tansformAndMoveDeclarationsToModuleScope(s, ast, asyncImports, variablePrefix) {
|
|
156
153
|
let moduleScopeEnd = 0;
|
|
157
154
|
let i = 0;
|
|
158
155
|
for (const node of ast.body) {
|
|
159
156
|
if (asyncImports.includes(node)) {
|
|
160
|
-
const tlaImport =
|
|
161
|
-
s
|
|
157
|
+
const tlaImport = `\nimport { ${variablePrefix}_access as ${variablePrefix}${i}} from '${node.source.value}';`;
|
|
158
|
+
s.appendLeft(node.end, tlaImport);
|
|
162
159
|
i++;
|
|
163
160
|
}
|
|
164
161
|
if (node.type === "ExportNamedDeclaration") {
|
|
165
162
|
if (node.declaration?.type === "VariableDeclaration") {
|
|
166
|
-
s
|
|
167
|
-
s
|
|
168
|
-
|
|
163
|
+
s.appendLeft(moduleScopeEnd, "export ");
|
|
164
|
+
s.remove(node.start, node.declaration.start);
|
|
165
|
+
moveVariableDeclarationToModuleScope(s, node.declaration, moduleScopeEnd);
|
|
169
166
|
}
|
|
170
|
-
} else if (node.type === "VariableDeclaration") if (node.kind.endsWith("using"))
|
|
171
|
-
else
|
|
167
|
+
} else if (node.type === "VariableDeclaration") if (node.kind.endsWith("using")) moveVariableDeclarationWithUsingToModuleScope(s, node, moduleScopeEnd, variablePrefix);
|
|
168
|
+
else moveVariableDeclarationToModuleScope(s, node, moduleScopeEnd);
|
|
172
169
|
else visitScope(node, (n) => {
|
|
173
|
-
if (n.type === "VariableDeclaration" && n.kind === "var")
|
|
170
|
+
if (n.type === "VariableDeclaration" && n.kind === "var") moveVariableDeclarationToModuleScope(s, n, moduleScopeEnd);
|
|
174
171
|
return false;
|
|
175
172
|
});
|
|
176
173
|
if (node.type === "ExportDefaultDeclaration" && !isDeclaration(node.declaration.type)) {
|
|
177
|
-
s
|
|
178
|
-
s
|
|
179
|
-
s
|
|
180
|
-
s
|
|
174
|
+
s.appendLeft(moduleScopeEnd, `let ${variablePrefix}_default;\nexport { ${variablePrefix}_default as default };\n`);
|
|
175
|
+
s.remove(node.start, node.declaration.start);
|
|
176
|
+
s.appendRight(node.declaration.start, `${variablePrefix}_default = (`);
|
|
177
|
+
s.appendLeft(node.declaration.end, ");");
|
|
181
178
|
}
|
|
182
179
|
if (isDeclaration(node.type) || node.type === "ImportDeclaration" || node.type === "ExportDefaultDeclaration" && isDeclaration(node.declaration.type) || node.type === "ExportNamedDeclaration" && isDeclaration(node.declaration?.type) || node.type === "ExportNamedDeclaration" && node.declaration == null || node.type === "ExportAllDeclaration") if (node.start > moduleScopeEnd) {
|
|
183
|
-
s
|
|
184
|
-
s
|
|
180
|
+
s.appendLeft(node.end, "\n");
|
|
181
|
+
s.move(node.start, node.end, moduleScopeEnd);
|
|
182
|
+
s.appendLeft(node.start, ";");
|
|
185
183
|
} else moduleScopeEnd = node.end;
|
|
186
184
|
}
|
|
187
|
-
return
|
|
185
|
+
return moduleScopeEnd;
|
|
188
186
|
}
|
|
189
187
|
function isDeclaration(type) {
|
|
190
188
|
return type === "ClassDeclaration" || type === "FunctionDeclaration";
|
|
@@ -192,20 +190,20 @@ function isDeclaration(type) {
|
|
|
192
190
|
function moveVariableDeclarationToModuleScope(s, node, declarationsEnd) {
|
|
193
191
|
const kind = replaceConstWithLet(node.kind);
|
|
194
192
|
const names = node.declarations.flatMap((decl) => getNames(decl.id)).join(", ");
|
|
195
|
-
s
|
|
196
|
-
s
|
|
197
|
-
s
|
|
198
|
-
s
|
|
193
|
+
s.appendRight(node.declarations[0].start, ";(");
|
|
194
|
+
s.appendLeft(node.declarations[node.declarations.length - 1].end, ")");
|
|
195
|
+
s.appendLeft(declarationsEnd, `${kind} ${names};\n`);
|
|
196
|
+
s.remove(node.start, node.declarations[0].start);
|
|
199
197
|
return s;
|
|
200
198
|
}
|
|
201
|
-
function moveVariableDeclarationWithUsingToModuleScope(s, node, declarationsEnd) {
|
|
199
|
+
function moveVariableDeclarationWithUsingToModuleScope(s, node, declarationsEnd, variablePrefix) {
|
|
202
200
|
node.declarations.forEach((declaration) => {
|
|
203
201
|
const id = declaration.id;
|
|
204
202
|
if (id.type !== "Identifier") throw new Error("'using' declarations may not have binding patterns.");
|
|
205
203
|
const name = id.name;
|
|
206
|
-
s
|
|
207
|
-
s
|
|
208
|
-
s
|
|
204
|
+
s.appendRight(id.start, `${variablePrefix}_using_`);
|
|
205
|
+
s.appendLeft(node.end, `\n${name} = ${variablePrefix}_using_${name};`);
|
|
206
|
+
s.appendLeft(declarationsEnd, `let ${name};\n`);
|
|
209
207
|
});
|
|
210
208
|
return s;
|
|
211
209
|
}
|
|
@@ -260,8 +258,8 @@ function concurrentTopLevelAwait(options = {}) {
|
|
|
260
258
|
return declaration;
|
|
261
259
|
}))).filter(Boolean);
|
|
262
260
|
if (!(asyncImports.length > 0 || hasAwait)) return;
|
|
263
|
-
|
|
264
|
-
|
|
261
|
+
const s = new MagicString(code);
|
|
262
|
+
transform(s, ast, asyncImports, hasAwait, options.generatedVariablePrefix ?? "__tla");
|
|
265
263
|
return {
|
|
266
264
|
code: s.toString(),
|
|
267
265
|
map: options.sourceMap !== false ? s.generateMap({ hires: true }) : null
|
package/package.json
CHANGED