rolldown-plugin-concurrent-top-level-await 0.0.3 → 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 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\//` | 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,16 +44,16 @@ 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
49
  const key$1 = importer.slice(proxyPrefix.length);
18
50
  const resolved$1 = awaitedEntriesMap.get(key$1);
19
51
  if (!resolved$1) throw new Error("Name collision in concurrent-tla plugin, please change the generatedVariablePrefix option");
20
52
  return resolved$1;
21
53
  }
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;
54
+ if (!extraOptions.isEntry && extraOptions.kind !== "dynamic-import") return;
55
+ const resolved = await this.resolve(source, importer, extraOptions);
56
+ if (resolved == null || !options.filter.includes(resolved.id)) return;
25
57
  const key = randomUUID();
26
58
  awaitedEntriesMap.set(key, resolved);
27
59
  return `${proxyPrefix}${key}`;
@@ -379,12 +411,8 @@ const supportedModuleTypes = new Set([
379
411
  "ts",
380
412
  "tsx"
381
413
  ]);
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
- });
414
+ function resolveDeclarationSource(context, id, declaration) {
415
+ return context.resolve(declaration.source.value, id, { custom: {} });
388
416
  }
389
417
  function transformPlugin(options) {
390
418
  const generatedVariablePrefix = options.generatedVariablePrefix;
@@ -392,42 +420,44 @@ function transformPlugin(options) {
392
420
  return {
393
421
  name: "rolldown-plugin-concurrent-tla-plugin-transform",
394
422
  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;
423
+ transform: {
424
+ filter: { id: withExclude(options.filter, prefixRegex(`\0${generatedVariablePrefix}AwaitEntry:`)) },
425
+ async handler(_code, id, transformOptions) {
426
+ if (!supportedModuleTypes.has(transformOptions?.moduleType)) {
427
+ asyncTracker.setEntryAsync(id, false);
428
+ asyncTracker.setDependencies(id, []);
429
+ }
430
+ const code = (await transform(id, _code)).code;
431
+ const ast = this.parse(code);
432
+ const importDeclarations = ast.body.filter((a) => a.type === "ImportDeclaration");
433
+ const hasAwait = hasTopLevelAwait(ast);
434
+ asyncTracker.setEntryAsync(id, hasAwait);
435
+ if (hasAwait) asyncTracker.setDependencies(id, []);
436
+ let imports = (await Promise.all(importDeclarations.map(async (declaration) => {
437
+ const importId = await resolveDeclarationSource(this, id, declaration);
438
+ if (!importId || !options.filter.includes(importId.id)) return null;
439
+ return {
440
+ declaration,
441
+ id: importId.id
442
+ };
443
+ }))).filter(Boolean);
444
+ if (!hasAwait) asyncTracker.setDependencies(id, imports.map((x) => x.id));
445
+ const asyncImports = (await Promise.all(imports.map(async ({ declaration, id: id$1 }) => {
446
+ this.load({ id: id$1 });
447
+ if (!await asyncTracker.isAsync(id$1)) return null;
448
+ return declaration;
449
+ }))).filter(Boolean);
450
+ if (!(asyncImports.length > 0 || hasAwait)) return;
451
+ const { magicString: _magicString } = transformOptions;
452
+ const magicString = new RolldownMagicString(code);
453
+ if (!_magicString) throw new Error("experimental.nativeMagicString must be enabled in the Rolldown options to use the concurrent-tla plugin");
454
+ transform$1(magicString, ast, options.registerModuleSource, asyncImports, hasAwait, generatedVariablePrefix);
410
455
  return {
411
- declaration,
412
- id: importId.id
456
+ code: magicString,
457
+ meta: { [generatedVariablePrefix + "_async"]: true }
413
458
  };
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
- } }
459
+ }
460
+ }
431
461
  };
432
462
  }
433
463
 
@@ -438,7 +468,8 @@ function concurrentTopLevelAwait(options = {}) {
438
468
  const enrichedOptions = {
439
469
  ...options,
440
470
  generatedVariablePrefix,
441
- registerModuleSource: `\0${generatedVariablePrefix}Register`
471
+ registerModuleSource: `\0${generatedVariablePrefix}Register`,
472
+ filter: createFilter(options.include, options.exclude ?? /\/node_modules\//)
442
473
  };
443
474
  return [
444
475
  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.1.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"