rolldown-plugin-concurrent-top-level-await 0.0.2 → 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 +4 -2
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +76 -45
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
> [!Warning]
|
|
2
|
-
> This plugin is currently in development.
|
|
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,
|
|
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 (!
|
|
23
|
-
const resolved = await this.resolve(source, importer,
|
|
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,
|
|
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: {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
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
|
-
|
|
412
|
-
|
|
456
|
+
code: magicString,
|
|
457
|
+
meta: { [generatedVariablePrefix + "_async"]: true }
|
|
413
458
|
};
|
|
414
|
-
}
|
|
415
|
-
|
|
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
|
+
"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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/zOadT/concurrent-top-level-await-plugins/tree/main/packages/rolldown-plugin#readme",
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"rolldown": "^1.0.0-rc.0",
|
|
36
|
+
"rolldown": "^1.0.0 || ^1.0.0-rc.0",
|
|
37
37
|
"vite": "^8.0.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
@@ -51,10 +51,8 @@
|
|
|
51
51
|
"reason": "Uses Rolldown-specific APIs"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"@rolldown/pluginutils": "1.0.0-rc.9"
|
|
56
|
-
},
|
|
57
54
|
"devDependencies": {
|
|
55
|
+
"@oxc-project/types": "^0.122.0",
|
|
58
56
|
"@types/estree": "^1.0.8",
|
|
59
57
|
"prettier": "3.7.4",
|
|
60
58
|
"rolldown": "1.0.0-rc.9"
|