rolldown-plugin-concurrent-top-level-await 0.0.3 → 0.2.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  > [!Warning]
2
- > This plugin is currently in development. A filter option will be added soon. For more information, see [this issue](https://github.com/zOadT/concurrent-top-level-await-plugins/issues/35).
2
+ > This plugin is currently in development. For more information, see [this issue](https://github.com/zOadT/concurrent-top-level-await-plugins/issues/35).
3
3
 
4
4
  # rolldown-plugin-concurrent-top-level-await
5
5
 
@@ -45,7 +45,9 @@ export default defineConfig({
45
45
  ## Options
46
46
 
47
47
  | Option | Type | Default | Description |
48
- | ------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------- |
48
+ | ------------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
49
+ | `include` | `RegExp | RegExp[]` | `undefined` | A RegExp specifying which files to include. See [below](#which-modules-to-include) to determine which modules to include. |
50
+ | `exclude` | `RegExp | RegExp[]` | `[/\/node_modules\//, /\.html$/]` | A RegExp specifying which files to exclude. Must still follow the [same considerations](#which-modules-to-include) as `include`. |
49
51
  | `generatedVariablePrefix` | `string` | `"__tla"` | Prefix used for internal variables generated by the plugin. Change this if it conflicts with variable names in your code. |
50
52
 
51
53
  ### Which modules to include?
package/dist/index.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  //#region src/index.d.ts
2
2
  declare function concurrentTopLevelAwait(options?: {
3
+ include?: RegExp | RegExp[];
4
+ exclude?: RegExp | RegExp[];
3
5
  /**
4
6
  * Prefix used for internal variables generated by the plugin.
5
7
  * Change this if it conflicts with variable names in your code.
package/dist/index.mjs CHANGED
@@ -2,6 +2,38 @@ import { randomUUID } from "node:crypto";
2
2
  import { RolldownMagicString } from "rolldown";
3
3
  import { transform } from "rolldown/utils";
4
4
 
5
+ //#region src/utils/filter.ts
6
+ function matchesPattern(id, pattern) {
7
+ if (Array.isArray(pattern)) return pattern.some((p) => p.test(id));
8
+ return pattern.test(id);
9
+ }
10
+ function createFilter(include, exclude) {
11
+ return {
12
+ include,
13
+ exclude,
14
+ includes(id) {
15
+ if (exclude && matchesPattern(id, exclude)) return false;
16
+ if (include) return matchesPattern(id, include);
17
+ return true;
18
+ }
19
+ };
20
+ }
21
+ function ensureArray(item) {
22
+ if (item == null) return [];
23
+ return Array.isArray(item) ? item : [item];
24
+ }
25
+ function withExclude(filter, exclude) {
26
+ return createFilter(filter.include, [...ensureArray(filter.exclude), exclude]);
27
+ }
28
+ function prefixRegex(str, flags) {
29
+ return new RegExp(`^${escapeRegex(str)}`, flags);
30
+ }
31
+ const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
32
+ function escapeRegex(str) {
33
+ return str.replace(escapeRegexRE, "\\$&");
34
+ }
35
+
36
+ //#endregion
5
37
  //#region src/awaitEntriesPlugin.ts
6
38
  function awaitEntrypointsPlugin(options) {
7
39
  const generatedVariablePrefix = options.generatedVariablePrefix;
@@ -12,19 +44,20 @@ function awaitEntrypointsPlugin(options) {
12
44
  apply: "build",
13
45
  resolveId: {
14
46
  order: "pre",
15
- async handler(source, importer, options$1) {
47
+ async handler(source, importer, extraOptions) {
16
48
  if (importer?.startsWith(proxyPrefix)) {
17
- const key$1 = importer.slice(proxyPrefix.length);
18
- const resolved$1 = awaitedEntriesMap.get(key$1);
19
- if (!resolved$1) throw new Error("Name collision in concurrent-tla plugin, please change the generatedVariablePrefix option");
20
- return resolved$1;
49
+ const key = importer.slice(proxyPrefix.length);
50
+ const resolved = awaitedEntriesMap.get(key);
51
+ if (!resolved) throw new Error("Name collision in concurrent-tla plugin, please change the generatedVariablePrefix option");
52
+ return resolved;
53
+ }
54
+ if (extraOptions.isEntry || extraOptions.kind === "dynamic-import" || importer != null && !options.filter.includes(importer)) {
55
+ const resolved = await this.resolve(source, importer, extraOptions);
56
+ if (resolved == null || !options.filter.includes(resolved.id)) return;
57
+ const key = randomUUID();
58
+ awaitedEntriesMap.set(key, resolved);
59
+ return `${proxyPrefix}${key}`;
21
60
  }
22
- if (!options$1.isEntry && options$1.kind !== "dynamic-import") return;
23
- const resolved = await this.resolve(source, importer, options$1);
24
- if (resolved == null) return;
25
- const key = randomUUID();
26
- awaitedEntriesMap.set(key, resolved);
27
- return `${proxyPrefix}${key}`;
28
61
  }
29
62
  },
30
63
  load: {
@@ -379,12 +412,9 @@ const supportedModuleTypes = new Set([
379
412
  "ts",
380
413
  "tsx"
381
414
  ]);
382
- function resolveDeclarationSource(context, id, importerAttributes = {}, declaration) {
383
- return context.resolve(declaration.source.value, id, {
384
- attributes: Object.fromEntries(declaration.attributes.map((attr) => [attr.key.type === "Identifier" ? attr.key.name : attr.key.value, attr.value.value])),
385
- importerAttributes,
386
- custom: {}
387
- });
415
+ let nativeMagicStringWarned = false;
416
+ function resolveDeclarationSource(context, id, declaration) {
417
+ return context.resolve(declaration.source.value, id, { custom: {} });
388
418
  }
389
419
  function transformPlugin(options) {
390
420
  const generatedVariablePrefix = options.generatedVariablePrefix;
@@ -392,42 +422,47 @@ function transformPlugin(options) {
392
422
  return {
393
423
  name: "rolldown-plugin-concurrent-tla-plugin-transform",
394
424
  apply: "build",
395
- transform: { async handler(_code, id, transformOptions) {
396
- if (id.startsWith(`\0${generatedVariablePrefix}AwaitEntry:`)) return;
397
- if (!supportedModuleTypes.has(transformOptions?.moduleType)) {
398
- asyncTracker.setEntryAsync(id, false);
399
- asyncTracker.setDependencies(id, []);
400
- }
401
- const code = (await transform(id, _code)).code;
402
- const ast = this.parse(code);
403
- const importDeclarations = ast.body.filter((a) => a.type === "ImportDeclaration");
404
- const hasAwait = hasTopLevelAwait(ast);
405
- asyncTracker.setEntryAsync(id, hasAwait);
406
- if (hasAwait) asyncTracker.setDependencies(id, []);
407
- let imports = (await Promise.all(importDeclarations.map(async (declaration) => {
408
- const importId = await resolveDeclarationSource(this, id, transformOptions?.attributes, declaration);
409
- if (!importId) return null;
425
+ transform: {
426
+ filter: { id: withExclude(options.filter, prefixRegex(`\0${generatedVariablePrefix}AwaitEntry:`)) },
427
+ async handler(_code, id, transformOptions) {
428
+ if (!supportedModuleTypes.has(transformOptions?.moduleType)) {
429
+ asyncTracker.setEntryAsync(id, false);
430
+ asyncTracker.setDependencies(id, []);
431
+ }
432
+ const code = (await transform(id, _code)).code;
433
+ const ast = this.parse(code);
434
+ const importDeclarations = ast.body.filter((a) => a.type === "ImportDeclaration");
435
+ const hasAwait = hasTopLevelAwait(ast);
436
+ asyncTracker.setEntryAsync(id, hasAwait);
437
+ if (hasAwait) asyncTracker.setDependencies(id, []);
438
+ let imports = (await Promise.all(importDeclarations.map(async (declaration) => {
439
+ const importId = await resolveDeclarationSource(this, id, declaration);
440
+ if (!importId || !options.filter.includes(importId.id)) return null;
441
+ return {
442
+ declaration,
443
+ id: importId.id
444
+ };
445
+ }))).filter(Boolean);
446
+ if (!hasAwait) asyncTracker.setDependencies(id, imports.map((x) => x.id));
447
+ const asyncImports = (await Promise.all(imports.map(async ({ declaration, id: id$1 }) => {
448
+ this.load({ id: id$1 });
449
+ if (!await asyncTracker.isAsync(id$1)) return null;
450
+ return declaration;
451
+ }))).filter(Boolean);
452
+ if (!(asyncImports.length > 0 || hasAwait)) return;
453
+ const { magicString: _magicString } = transformOptions;
454
+ const magicString = new RolldownMagicString(code);
455
+ if (!_magicString && !nativeMagicStringWarned) {
456
+ this.warn("Enable experimental.nativeMagicString for source maps support");
457
+ nativeMagicStringWarned = true;
458
+ }
459
+ transform$1(magicString, ast, options.registerModuleSource, asyncImports, hasAwait, generatedVariablePrefix);
410
460
  return {
411
- declaration,
412
- id: importId.id
461
+ code: _magicString != null ? magicString : magicString.toString(),
462
+ meta: { [generatedVariablePrefix + "_async"]: true }
413
463
  };
414
- }))).filter(Boolean);
415
- if (!hasAwait) asyncTracker.setDependencies(id, imports.map((x) => x.id));
416
- const asyncImports = (await Promise.all(imports.map(async ({ declaration, id: id$1 }) => {
417
- this.load({ id: id$1 });
418
- if (!await asyncTracker.isAsync(id$1)) return null;
419
- return declaration;
420
- }))).filter(Boolean);
421
- if (!(asyncImports.length > 0 || hasAwait)) return;
422
- const { magicString: _magicString } = transformOptions;
423
- const magicString = new RolldownMagicString(code);
424
- if (!_magicString) throw new Error("experimental.nativeMagicString must be enabled in the Rolldown options to use the concurrent-tla plugin");
425
- transform$1(magicString, ast, options.registerModuleSource, asyncImports, hasAwait, generatedVariablePrefix);
426
- return {
427
- code: magicString,
428
- meta: { [generatedVariablePrefix + "_async"]: true }
429
- };
430
- } }
464
+ }
465
+ }
431
466
  };
432
467
  }
433
468
 
@@ -438,7 +473,8 @@ function concurrentTopLevelAwait(options = {}) {
438
473
  const enrichedOptions = {
439
474
  ...options,
440
475
  generatedVariablePrefix,
441
- registerModuleSource: `\0${generatedVariablePrefix}Register`
476
+ registerModuleSource: `\0${generatedVariablePrefix}Register`,
477
+ filter: createFilter(options.include, options.exclude ?? [/\/node_modules\//, /\.html$/])
442
478
  };
443
479
  return [
444
480
  awaitEntrypointsPlugin(enrichedOptions),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rolldown-plugin-concurrent-top-level-await",
3
- "version": "0.0.3",
3
+ "version": "0.2.0",
4
4
  "description": "Rolldown (and Vite) plugin enabling concurrent execution of modules that contain top level await.",
5
5
  "keywords": [
6
6
  "rolldown-plugin",
@@ -52,6 +52,7 @@
52
52
  }
53
53
  },
54
54
  "devDependencies": {
55
+ "@oxc-project/types": "^0.122.0",
55
56
  "@types/estree": "^1.0.8",
56
57
  "prettier": "3.7.4",
57
58
  "rolldown": "1.0.0-rc.9"