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 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): "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\n return evaluate;\n\n function evaluate(whenDone, onError) {\n if (state === \"done\") {\n if (whenDone)\n whenDone();\n return;\n }\n if (state === \"failed\") {\n if (onError)\n onError(error);\n return;\n }\n if (whenDone)\n whenDones.push(whenDone);\n if (onError)\n 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)\n x();\n };\n let moduleError = (err) => {\n state = \"failed\";\n error = err;\n for (let x of whenErrors)\n x(err);\n };\n let importDone = () => {\n if (state !== \"busy\")\n return;\n if (--remaining !== 0)\n return;\n try {\n let result = fn();\n if (result) {\n result\n .then(moduleDone)\n .catch(moduleError);\n }\n else {\n moduleDone();\n }\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)\n continue;\n }\n catch (_a) {\n continue;\n }\n remaining++;\n evaluate(importDone, moduleError);\n }\n importDone();\n }\n}\n" | undefined;
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.prepend(`import ${variablePrefix}_register from ${JSON.stringify(registerModuleSource)};\n`);
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 i = 0;
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}${i}} from '${node.source.value}';`;
150
+ const tlaImport = `\nimport { ${variablePrefix}_access as ${variablePrefix}${importDeclarationIndex}} from '${node.source.value}';`;
146
151
  s.appendLeft(node.end, tlaImport);
147
- i++;
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 registerModuleSource = `\0${options.generatedVariablePrefix ?? "__tla"}Register`;
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 tlaModule;
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, options.generatedVariablePrefix ?? "__tla");
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.1",
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"