rollup-plugin-concurrent-top-level-await 0.3.1 → 0.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/dist/index.d.mts +1 -1
- package/dist/index.mjs +31 -94
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -18,7 +18,7 @@ declare function concurrentTopLevelAwait(options?: {
|
|
|
18
18
|
name: string;
|
|
19
19
|
apply: "build";
|
|
20
20
|
resolveId(this: rollup0.PluginContext, source: string): string | undefined;
|
|
21
|
-
load(this: rollup0.PluginContext, id: string):
|
|
21
|
+
load(this: rollup0.PluginContext, id: string): string | undefined;
|
|
22
22
|
transform: {
|
|
23
23
|
handler(this: TransformPluginContext, code: string, id: string, transformOptions: {
|
|
24
24
|
ssr?: boolean | undefined;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createFilter } from "@rollup/pluginutils";
|
|
2
2
|
import MagicString from "magic-string";
|
|
3
3
|
|
|
4
|
-
//#region src/ast.ts
|
|
4
|
+
//#region ../shared/src/ast.ts
|
|
5
5
|
function isFunctionNode(node) {
|
|
6
6
|
return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "MethodDefinition" || node.type === "Property" && node.value.type === "FunctionExpression";
|
|
7
7
|
}
|
|
@@ -13,7 +13,7 @@ function visitScope(node, cb) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
//#endregion
|
|
16
|
-
//#region src/hasTopLevelAwait.ts
|
|
16
|
+
//#region ../shared/src/hasTopLevelAwait.ts
|
|
17
17
|
function isAwaitNode(node) {
|
|
18
18
|
return node.type === "AwaitExpression" || node.type === "ForOfStatement" && node.await || node.type === "VariableDeclaration" && node.kind === "await using";
|
|
19
19
|
}
|
|
@@ -22,7 +22,7 @@ function hasTopLevelAwait(node) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region src/polyfills/promise.ts
|
|
25
|
+
//#region ../shared/src/polyfills/promise.ts
|
|
26
26
|
function withResolvers() {
|
|
27
27
|
let resolve;
|
|
28
28
|
let reject;
|
|
@@ -37,7 +37,7 @@ function withResolvers() {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
//#endregion
|
|
40
|
-
//#region src/AsyncModuleTracker.ts
|
|
40
|
+
//#region ../shared/src/AsyncModuleTracker.ts
|
|
41
41
|
var AwaitableCache = class {
|
|
42
42
|
#store = /* @__PURE__ */ new Map();
|
|
43
43
|
#getPromise(key) {
|
|
@@ -127,24 +127,29 @@ var AsyncModuleTracker = class {
|
|
|
127
127
|
};
|
|
128
128
|
|
|
129
129
|
//#endregion
|
|
130
|
-
//#region src/transform.ts
|
|
130
|
+
//#region ../shared/src/transform.ts
|
|
131
131
|
function transform(s, ast, registerModuleSource, asyncImports, hasAwait, variablePrefix) {
|
|
132
132
|
const declarationsEnd = transformAndMoveDeclarationsToModuleScope(s, ast, asyncImports, variablePrefix);
|
|
133
133
|
s.appendRight(declarationsEnd, `${hasAwait ? "async " : ""}function ${variablePrefix}_initModuleExports() {\n`);
|
|
134
134
|
s.append("\n}\n");
|
|
135
|
-
s.
|
|
135
|
+
s.append(`import ${variablePrefix}_register from ${JSON.stringify(registerModuleSource)};\n`);
|
|
136
136
|
const asyncDeps = `[${asyncImports.map((_, i) => `() => ${variablePrefix}${i}`).join(", ")}]`;
|
|
137
137
|
s.append(`export const ${variablePrefix}_access = ${variablePrefix}_register(${variablePrefix}_initModuleExports, ${asyncDeps});\n`);
|
|
138
|
-
s.append(`if (import.meta.useTla) await new Promise(${variablePrefix}_access);\n`);
|
|
139
138
|
}
|
|
140
139
|
function transformAndMoveDeclarationsToModuleScope(s, ast, asyncImports, variablePrefix) {
|
|
141
140
|
let moduleScopeEnd = 0;
|
|
142
|
-
let
|
|
141
|
+
let importDeclarationIndex = 0;
|
|
142
|
+
let inDirectivePrologue = true;
|
|
143
143
|
for (const node of ast.body) {
|
|
144
|
+
if (inDirectivePrologue && node.type === "ExpressionStatement" && node.expression.type === "Literal") {
|
|
145
|
+
moduleScopeEnd = node.end;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
inDirectivePrologue = false;
|
|
144
149
|
if (asyncImports.includes(node)) {
|
|
145
|
-
const tlaImport = `\nimport { ${variablePrefix}_access as ${variablePrefix}${
|
|
150
|
+
const tlaImport = `\nimport { ${variablePrefix}_access as ${variablePrefix}${importDeclarationIndex}} from '${node.source.value}';`;
|
|
146
151
|
s.appendLeft(node.end, tlaImport);
|
|
147
|
-
|
|
152
|
+
importDeclarationIndex++;
|
|
148
153
|
}
|
|
149
154
|
if (node.type === "ClassDeclaration") {
|
|
150
155
|
s.appendLeft(moduleScopeEnd, `let ${node.id.name};\n`);
|
|
@@ -187,6 +192,7 @@ function isFunctionDeclaration(type) {
|
|
|
187
192
|
return type === "FunctionDeclaration";
|
|
188
193
|
}
|
|
189
194
|
function getClassDeclarationStart(node) {
|
|
195
|
+
if (!("decorators" in node)) return node.start;
|
|
190
196
|
return node.decorators[0]?.start ?? node.start;
|
|
191
197
|
}
|
|
192
198
|
function moveVariableDeclarationToModuleScope(s, node, declarationsEnd) {
|
|
@@ -229,6 +235,16 @@ function getNames(pattern) {
|
|
|
229
235
|
}
|
|
230
236
|
}
|
|
231
237
|
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region ../shared/src/registerSource.ts
|
|
240
|
+
var registerSource_default = {
|
|
241
|
+
"code": "export default function register(fn, evaluate_accesses) {\n let state = \"ready\";\n let whenDones = [];\n let whenErrors = [];\n let remaining = 1;\n let error = undefined;\n // evaluate eagerly\n evaluate();\n return evaluate;\n function evaluate(whenDone, onError) {\n if (state === \"done\") {\n if (whenDone) whenDone();\n return;\n }\n if (state === \"failed\") {\n if (onError) onError(error);\n return;\n }\n if (whenDone) whenDones.push(whenDone);\n if (onError) whenErrors.push(onError);\n if (state === \"busy\") {\n return;\n }\n state = \"busy\";\n let moduleDone = () => {\n state = \"done\";\n for (let x of whenDones) x();\n };\n let moduleError = (err) => {\n state = \"failed\";\n error = err;\n for (let x of whenErrors) x(err);\n };\n let importDone = () => {\n if (state !== \"busy\") return;\n if (--remaining !== 0) return;\n try {\n let result = fn();\n if (result) {\n result.then(moduleDone).catch(moduleError);\n } else {\n moduleDone();\n }\n } catch (err) {\n moduleError(err);\n }\n };\n for (const access of evaluate_accesses) {\n let evaluate;\n try {\n // Environment-dependent behavior:\n // - throws on cyclic dependencies in V8\n // - returns undefined in some environments (e.g., vitest)\n evaluate = access();\n if (evaluate == null) continue;\n } catch {\n continue;\n }\n remaining++;\n evaluate(importDone, moduleError);\n }\n importDone();\n }\n}\n",
|
|
242
|
+
"helpersUsed": {},
|
|
243
|
+
"errors": [],
|
|
244
|
+
"warnings": [],
|
|
245
|
+
"tsconfigFilePaths": []
|
|
246
|
+
}.code;
|
|
247
|
+
|
|
232
248
|
//#endregion
|
|
233
249
|
//#region src/index.ts
|
|
234
250
|
function resolveDeclarationSource(context, id, importerAttributes = {}, declaration) {
|
|
@@ -238,90 +254,10 @@ function resolveDeclarationSource(context, id, importerAttributes = {}, declarat
|
|
|
238
254
|
custom: {}
|
|
239
255
|
});
|
|
240
256
|
}
|
|
241
|
-
const tlaModule = `export default function register(fn, evaluate_accesses) {
|
|
242
|
-
let state = "ready";
|
|
243
|
-
let whenDones = [];
|
|
244
|
-
let whenErrors = [];
|
|
245
|
-
let remaining = 1;
|
|
246
|
-
let error = undefined;
|
|
247
|
-
// evaluate eagerly
|
|
248
|
-
evaluate();
|
|
249
|
-
|
|
250
|
-
return evaluate;
|
|
251
|
-
|
|
252
|
-
function evaluate(whenDone, onError) {
|
|
253
|
-
if (state === "done") {
|
|
254
|
-
if (whenDone)
|
|
255
|
-
whenDone();
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
if (state === "failed") {
|
|
259
|
-
if (onError)
|
|
260
|
-
onError(error);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
if (whenDone)
|
|
264
|
-
whenDones.push(whenDone);
|
|
265
|
-
if (onError)
|
|
266
|
-
whenErrors.push(onError);
|
|
267
|
-
if (state === "busy") {
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
state = "busy";
|
|
271
|
-
let moduleDone = () => {
|
|
272
|
-
state = "done";
|
|
273
|
-
for (let x of whenDones)
|
|
274
|
-
x();
|
|
275
|
-
};
|
|
276
|
-
let moduleError = (err) => {
|
|
277
|
-
state = "failed";
|
|
278
|
-
error = err;
|
|
279
|
-
for (let x of whenErrors)
|
|
280
|
-
x(err);
|
|
281
|
-
};
|
|
282
|
-
let importDone = () => {
|
|
283
|
-
if (state !== "busy")
|
|
284
|
-
return;
|
|
285
|
-
if (--remaining !== 0)
|
|
286
|
-
return;
|
|
287
|
-
try {
|
|
288
|
-
let result = fn();
|
|
289
|
-
if (result) {
|
|
290
|
-
result
|
|
291
|
-
.then(moduleDone)
|
|
292
|
-
.catch(moduleError);
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
moduleDone();
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
catch (err) {
|
|
299
|
-
moduleError(err);
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
for (const access of evaluate_accesses) {
|
|
303
|
-
let evaluate;
|
|
304
|
-
try {
|
|
305
|
-
// Environment-dependent behavior:
|
|
306
|
-
// - throws on cyclic dependencies in V8
|
|
307
|
-
// - returns undefined in some environments (e.g., vitest)
|
|
308
|
-
evaluate = access();
|
|
309
|
-
if (evaluate == null)
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
catch (_a) {
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
remaining++;
|
|
316
|
-
evaluate(importDone, moduleError);
|
|
317
|
-
}
|
|
318
|
-
importDone();
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
`;
|
|
322
257
|
function concurrentTopLevelAwait(options = {}) {
|
|
323
258
|
const filter = createFilter(options.include, options.exclude);
|
|
324
|
-
const
|
|
259
|
+
const generatedVariablePrefix = options.generatedVariablePrefix ?? "__tla";
|
|
260
|
+
const registerModuleSource = `\0${generatedVariablePrefix}Register`;
|
|
325
261
|
const asyncTracker = new AsyncModuleTracker();
|
|
326
262
|
return {
|
|
327
263
|
name: "rollup-plugin-concurrent-tla-plugin",
|
|
@@ -330,7 +266,7 @@ function concurrentTopLevelAwait(options = {}) {
|
|
|
330
266
|
if (source === registerModuleSource) return registerModuleSource;
|
|
331
267
|
},
|
|
332
268
|
load(id) {
|
|
333
|
-
if (id === registerModuleSource) return
|
|
269
|
+
if (id === registerModuleSource) return registerSource_default;
|
|
334
270
|
},
|
|
335
271
|
transform: { async handler(code, id, transformOptions) {
|
|
336
272
|
if (!filter(id)) return;
|
|
@@ -355,7 +291,8 @@ function concurrentTopLevelAwait(options = {}) {
|
|
|
355
291
|
}))).filter(Boolean);
|
|
356
292
|
if (!(asyncImports.length > 0 || hasAwait)) return;
|
|
357
293
|
const s = new MagicString(code);
|
|
358
|
-
transform(s, ast, registerModuleSource, asyncImports, hasAwait,
|
|
294
|
+
transform(s, ast, registerModuleSource, asyncImports, hasAwait, generatedVariablePrefix);
|
|
295
|
+
s.append(`if (import.meta.useTla) await new Promise(${generatedVariablePrefix}_access);\n`);
|
|
359
296
|
return {
|
|
360
297
|
code: s.toString(),
|
|
361
298
|
map: options.sourceMap !== false ? s.generateMap({ hires: true }) : null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rollup-plugin-concurrent-top-level-await",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Rollup (and Vite) plugin enabling concurrent execution of modules that contain top level await.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rollup-plugin",
|
|
@@ -58,7 +58,8 @@
|
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/estree": "^1.0.8",
|
|
60
60
|
"prettier": "3.7.4",
|
|
61
|
-
"rollup": "^4.57.1"
|
|
61
|
+
"rollup": "^4.57.1",
|
|
62
|
+
"unplugin-macros": "^0.19.1"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"build": "tsdown --dts"
|