@ohos-ports/rolldown 1.2.6-beta.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/LICENSE +25 -0
- package/README.md +11 -0
- package/THIRD-PARTY-LICENSE +33 -0
- package/bin/cli.mjs +11 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +1208 -0
- package/dist/config.d.mts +26 -0
- package/dist/config.mjs +4 -0
- package/dist/experimental-default-runtime.mjs +116 -0
- package/dist/experimental-index.d.mts +324 -0
- package/dist/experimental-index.mjs +383 -0
- package/dist/experimental-runtime-base.mjs +95 -0
- package/dist/experimental-runtime-types.d.ts +177 -0
- package/dist/experimental-runtime.d.ts +177 -0
- package/dist/experimental-runtime.mjs +257 -0
- package/dist/filter-index.d.mts +196 -0
- package/dist/filter-index.mjs +376 -0
- package/dist/get-log-filter.d.mts +3 -0
- package/dist/get-log-filter.mjs +68 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +56 -0
- package/dist/parallel-plugin-worker.d.mts +1 -0
- package/dist/parallel-plugin-worker.mjs +29 -0
- package/dist/parallel-plugin.d.mts +12 -0
- package/dist/parallel-plugin.mjs +6 -0
- package/dist/parse-ast-index.d.mts +30 -0
- package/dist/parse-ast-index.mjs +60 -0
- package/dist/plugins-index.d.mts +32 -0
- package/dist/plugins-index.mjs +40 -0
- package/dist/shared/binding-CtPG-2KR.mjs +675 -0
- package/dist/shared/binding-Og__jmUi.d.mts +2065 -0
- package/dist/shared/bindingify-input-options-4JJxbZl2.mjs +2416 -0
- package/dist/shared/constructors-Qrp2Xr6w.d.mts +35 -0
- package/dist/shared/constructors-ltBDfHX1.mjs +69 -0
- package/dist/shared/create-bundler-option-DSPiA5F7.mjs +3220 -0
- package/dist/shared/define-config-Demdg3_4.mjs +6 -0
- package/dist/shared/define-config-Nbz-lniw.d.mts +4101 -0
- package/dist/shared/dist-DKbukT1H.mjs +154 -0
- package/dist/shared/error-HDibX49O.mjs +85 -0
- package/dist/shared/get-log-filter-AjBknEEO.d.mts +34 -0
- package/dist/shared/load-config-BMUrE9HH.mjs +137 -0
- package/dist/shared/logging-xuHO4mAy.d.mts +50 -0
- package/dist/shared/logs-DmYCAKcW.mjs +192 -0
- package/dist/shared/misc-DOSKtd97.mjs +29 -0
- package/dist/shared/normalize-string-or-regex-DWz4it3p.mjs +68 -0
- package/dist/shared/parse-D0g29RgN.mjs +74 -0
- package/dist/shared/prompt-CH6TK0bC.mjs +885 -0
- package/dist/shared/resolve-tsconfig-CLYpUIZC.mjs +128 -0
- package/dist/shared/rolldown-C9Hfg50O.mjs +179 -0
- package/dist/shared/transform-DR4CXeQm.d.mts +152 -0
- package/dist/shared/watch-UbzgabQn.mjs +377 -0
- package/dist/utils-index.d.mts +375 -0
- package/dist/utils-index.mjs +2416 -0
- package/package.json +159 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Module } from "node:module";
|
|
2
|
+
import { MessageChannel } from "node:worker_threads";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
//#region ../../node_modules/.pnpm/fresh-import@0.2.1/node_modules/fresh-import/dist/index.js
|
|
5
|
+
const instanceId = Math.random().toString(36).slice(2);
|
|
6
|
+
const relativeImportRE = /^\.{1,2}(?:\/|\\)/;
|
|
7
|
+
function escapeRegExp(value) {
|
|
8
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The tracking query name `fresh-import-<instance>`, where `<instance>` is a
|
|
12
|
+
* random value unique to this loaded module instance. Any two instances (even
|
|
13
|
+
* two copies of the same build loaded into the same process) get distinct
|
|
14
|
+
* names, so each hook only recognizes the imports it tagged itself.
|
|
15
|
+
*/
|
|
16
|
+
function buildQueryName() {
|
|
17
|
+
return `fresh-import-${instanceId}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build the regex that matches the tracking query `?<name>=<id>,<context>`
|
|
21
|
+
* (or the `&<name>=...` form).
|
|
22
|
+
*/
|
|
23
|
+
function buildQueryRE(queryName) {
|
|
24
|
+
return new RegExp(`(?:\\?|&)${escapeRegExp(queryName)}=(\\d+),([^&]+)(?:&|$)`);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build the tracking query `?<name>=<id>,<context>` that `collect` appends to
|
|
28
|
+
* the entry specifier. `id` cache-busts the import (a distinct URL forces a
|
|
29
|
+
* fresh evaluation) and `context` tags the import graph so the resolve hook can
|
|
30
|
+
* attribute resolved dependencies back to the originating collect.
|
|
31
|
+
*/
|
|
32
|
+
function formatTrackingQuery(queryName, id, context) {
|
|
33
|
+
return `?${queryName}=${id},${context}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Shared body of the resolve hook for both the on-thread and off-thread
|
|
37
|
+
* importers. Given an already-resolved `result`, decides whether it is a tracked
|
|
38
|
+
* relative file dependency; if so, reports it via `onDependency` and tags the
|
|
39
|
+
* URL so the query propagates to its own dependencies.
|
|
40
|
+
*
|
|
41
|
+
* The sync/async difference between the two hooks lives entirely in the caller
|
|
42
|
+
* (which awaits `nextResolve` or not); this function performs no I/O. `result`
|
|
43
|
+
* is mutated in place and returned.
|
|
44
|
+
*/
|
|
45
|
+
function trackResolved(specifier, context, result, queryName, queryRE, onDependency) {
|
|
46
|
+
const isRelativeImport = relativeImportRE.test(specifier);
|
|
47
|
+
if (result.format === "builtin" || !isRelativeImport) return result;
|
|
48
|
+
if (!context.parentURL || queryRE.test(result.url) || !result.url.startsWith("file:")) return result;
|
|
49
|
+
const m = queryRE.exec(context.parentURL);
|
|
50
|
+
if (m) {
|
|
51
|
+
const [, id, contextFile] = m;
|
|
52
|
+
onDependency(contextFile, result.url);
|
|
53
|
+
result.url = result.url.replace(/(\?)|$/, (_n, n1) => `?${queryName}=${id},${contextFile}${n1 === "?" ? "&" : ""}`);
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
var loader_default = "data:text/javascript,Math.random().toString(36).slice(2);%0Aconst relativeImportRE = /^\\.{1,2}(%3F:\\/|\\\\)/;%0Afunction escapeRegExp(value) {%0A%09return value.replace(/[.*+%3F^${}()|[\\]\\\\]/g, \"\\\\$&\");%0A}%0A/**%0A* Build the regex that matches the tracking query `%3F<name>=<id>,<context>`%0A* (or the `&<name>=...` form).%0A*/%0Afunction buildQueryRE(queryName) {%0A%09return new RegExp(`(%3F:\\\\%3F|&)${escapeRegExp(queryName)}=(\\\\d+),([^&]+)(%3F:&|$)`);%0A}%0A/**%0A* Shared body of the resolve hook for both the on-thread and off-thread%0A* importers. Given an already-resolved `result`, decides whether it is a tracked%0A* relative file dependency; if so, reports it via `onDependency` and tags the%0A* URL so the query propagates to its own dependencies.%0A*%0A* The sync/async difference between the two hooks lives entirely in the caller%0A* (which awaits `nextResolve` or not); this function performs no I/O. `result`%0A* is mutated in place and returned.%0A*/%0Afunction trackResolved(specifier, context, result, queryName, queryRE, onDependency) {%0A%09const isRelativeImport = relativeImportRE.test(specifier);%0A%09if (result.format === \"builtin\" || !isRelativeImport) return result;%0A%09if (!context.parentURL || queryRE.test(result.url) || !result.url.startsWith(\"file:\")) return result;%0A%09const m = queryRE.exec(context.parentURL);%0A%09if (m) {%0A%09%09const [, id, contextFile] = m;%0A%09%09onDependency(contextFile, result.url);%0A%09%09result.url = result.url.replace(/(\\%3F)|$/, (_n, n1) => `%3F${queryName}=${id},${contextFile}${n1 === \"%3F\" %3F \"&\" : \"\"}`);%0A%09}%0A%09return result;%0A}%0A//%23endregion%0A//%23region src/off-thread/loader.ts%0Alet port;%0Alet queryName;%0Alet queryRE;%0Aconst initialize = async (data) => {%0A%09port = data.port;%0A%09queryName = data.queryName;%0A%09queryRE = buildQueryRE(queryName);%0A};%0Aconst resolve = async (specifier, context, nextResolve) => {%0A%09return trackResolved(specifier, context, await nextResolve(specifier, context), queryName, queryRE, (ctx, url) => {%0A%09%09port.postMessage({%0A%09%09%09context: ctx,%0A%09%09%09url%0A%09%09});%0A%09});%0A};%0A//%23endregion%0Aexport { initialize, resolve };%0A";
|
|
58
|
+
let nextId$1 = 0;
|
|
59
|
+
/**
|
|
60
|
+
* Off-thread importer: registers an ESM loader in a worker thread via
|
|
61
|
+
* `Module.register` and receives tracked dependencies over a `MessagePort`.
|
|
62
|
+
* Used on Node versions without `Module.registerHooks`.
|
|
63
|
+
*/
|
|
64
|
+
function createOffThreadImporter() {
|
|
65
|
+
const queryName = buildQueryName();
|
|
66
|
+
const { port1, port2 } = new MessageChannel();
|
|
67
|
+
Module.register(loader_default, {
|
|
68
|
+
data: {
|
|
69
|
+
port: port2,
|
|
70
|
+
queryName
|
|
71
|
+
},
|
|
72
|
+
transferList: [port2]
|
|
73
|
+
});
|
|
74
|
+
port1.unref();
|
|
75
|
+
return { async collect(specifier) {
|
|
76
|
+
const id = nextId$1++;
|
|
77
|
+
const depsList = /* @__PURE__ */ new Set();
|
|
78
|
+
const onMessage = (e) => {
|
|
79
|
+
if (e.context === specifier) depsList.add(e.url);
|
|
80
|
+
};
|
|
81
|
+
port1.on("message", onMessage);
|
|
82
|
+
port1.unref();
|
|
83
|
+
try {
|
|
84
|
+
const result = await import(specifier + formatTrackingQuery(queryName, id, specifier));
|
|
85
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
86
|
+
return {
|
|
87
|
+
result,
|
|
88
|
+
dependencies: [...depsList].filter((url) => url.startsWith("file:")).map((url) => fileURLToPath(url))
|
|
89
|
+
};
|
|
90
|
+
} finally {
|
|
91
|
+
port1.off("message", onMessage);
|
|
92
|
+
}
|
|
93
|
+
} };
|
|
94
|
+
}
|
|
95
|
+
let nextId = 0;
|
|
96
|
+
/**
|
|
97
|
+
* On-thread importer: registers synchronous resolution hooks via
|
|
98
|
+
* `Module.registerHooks` (Node 22.15+/23.5+).
|
|
99
|
+
*/
|
|
100
|
+
function createOnThreadImporter() {
|
|
101
|
+
const registry = /* @__PURE__ */ new Map();
|
|
102
|
+
const queryName = buildQueryName();
|
|
103
|
+
const queryRE = buildQueryRE(queryName);
|
|
104
|
+
const resolve = (specifier, context, nextResolve) => {
|
|
105
|
+
return trackResolved(specifier, context, nextResolve(specifier, context), queryName, queryRE, (ctx, url) => {
|
|
106
|
+
registry.get(ctx)?.add(url);
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
Module.registerHooks({ resolve });
|
|
110
|
+
return { async collect(specifier) {
|
|
111
|
+
const id = nextId++;
|
|
112
|
+
const depsList = /* @__PURE__ */ new Set();
|
|
113
|
+
registry.set(specifier, depsList);
|
|
114
|
+
try {
|
|
115
|
+
return {
|
|
116
|
+
result: await import(specifier + formatTrackingQuery(queryName, id, specifier)),
|
|
117
|
+
dependencies: [...depsList].filter((url) => url.startsWith("file:")).map((url) => fileURLToPath(url))
|
|
118
|
+
};
|
|
119
|
+
} finally {
|
|
120
|
+
registry.delete(specifier);
|
|
121
|
+
}
|
|
122
|
+
} };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Create the importer best suited to the current runtime, or `undefined` if it
|
|
126
|
+
* provides neither module-hook API.
|
|
127
|
+
*/
|
|
128
|
+
function createImporter() {
|
|
129
|
+
if (Module.registerHooks) return createOnThreadImporter();
|
|
130
|
+
if (Module.register) return createOffThreadImporter();
|
|
131
|
+
}
|
|
132
|
+
let importer;
|
|
133
|
+
let initialized = false;
|
|
134
|
+
/**
|
|
135
|
+
* Import an ESM entry in its own fresh module graph (separate from Node's module
|
|
136
|
+
* cache and from other concurrent imports) and report the dependency files it
|
|
137
|
+
* pulled in.
|
|
138
|
+
*
|
|
139
|
+
* Each call re-evaluates the entry in a fresh graph; concurrent calls stay
|
|
140
|
+
* isolated from one another. Only statically-imported relative dependencies are
|
|
141
|
+
* tracked, not dynamic imports.
|
|
142
|
+
*
|
|
143
|
+
* Returns `undefined` on runtimes that provide neither `Module.registerHooks`
|
|
144
|
+
* nor `Module.register`.
|
|
145
|
+
*/
|
|
146
|
+
function freshImport(specifier) {
|
|
147
|
+
if (!initialized) {
|
|
148
|
+
importer = createImporter();
|
|
149
|
+
initialized = true;
|
|
150
|
+
}
|
|
151
|
+
return importer?.collect(specifier);
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { freshImport };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { t as require_binding } from "./binding-CtPG-2KR.mjs";
|
|
2
|
+
//#region src/types/sourcemap.ts
|
|
3
|
+
function bindingifySourcemap(map) {
|
|
4
|
+
if (map == null) return;
|
|
5
|
+
return { inner: typeof map === "string" ? map : {
|
|
6
|
+
file: map.file ?? void 0,
|
|
7
|
+
mappings: map.mappings,
|
|
8
|
+
sourceRoot: "sourceRoot" in map ? map.sourceRoot ?? void 0 : void 0,
|
|
9
|
+
sources: map.sources?.map((s) => s ?? void 0),
|
|
10
|
+
sourcesContent: map.sourcesContent?.map((s) => s ?? void 0),
|
|
11
|
+
names: map.names,
|
|
12
|
+
x_google_ignoreList: map.x_google_ignoreList,
|
|
13
|
+
debugId: "debugId" in map ? map.debugId : void 0
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
require_binding();
|
|
17
|
+
function unwrapBindingResult(container) {
|
|
18
|
+
if (typeof container === "object" && container !== null && "isBindingErrors" in container && container.isBindingErrors) throw aggregateBindingErrorsIntoJsError(container.errors);
|
|
19
|
+
return container;
|
|
20
|
+
}
|
|
21
|
+
function normalizeBindingResult(container) {
|
|
22
|
+
if (typeof container === "object" && container !== null && "isBindingErrors" in container && container.isBindingErrors) return aggregateBindingErrorsIntoJsError(container.errors);
|
|
23
|
+
return container;
|
|
24
|
+
}
|
|
25
|
+
function normalizeBindingError(e) {
|
|
26
|
+
return e.type === "JsError" ? e.field0 : Object.assign(/* @__PURE__ */ new Error(), {
|
|
27
|
+
code: e.field0.kind,
|
|
28
|
+
kind: e.field0.kind,
|
|
29
|
+
message: e.field0.message,
|
|
30
|
+
id: e.field0.id,
|
|
31
|
+
exporter: e.field0.exporter,
|
|
32
|
+
loc: e.field0.loc,
|
|
33
|
+
pos: e.field0.pos,
|
|
34
|
+
stack: void 0
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function aggregateBindingErrorsIntoJsError(rawErrors) {
|
|
38
|
+
const errors = rawErrors.map(normalizeBindingError);
|
|
39
|
+
let summary = `Build failed with ${errors.length} error${errors.length < 2 ? "" : "s"}:\n`;
|
|
40
|
+
for (let i = 0; i < errors.length; i++) {
|
|
41
|
+
summary += "\n";
|
|
42
|
+
if (i >= 5) {
|
|
43
|
+
summary += "...";
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
summary += getErrorMessage(errors[i]);
|
|
47
|
+
}
|
|
48
|
+
const wrapper = new Error(summary);
|
|
49
|
+
Object.defineProperty(wrapper, "errors", {
|
|
50
|
+
configurable: true,
|
|
51
|
+
enumerable: true,
|
|
52
|
+
get: () => errors,
|
|
53
|
+
set: (value) => Object.defineProperty(wrapper, "errors", {
|
|
54
|
+
configurable: true,
|
|
55
|
+
enumerable: true,
|
|
56
|
+
value
|
|
57
|
+
})
|
|
58
|
+
});
|
|
59
|
+
return wrapper;
|
|
60
|
+
}
|
|
61
|
+
function getErrorMessage(e) {
|
|
62
|
+
if (Object.hasOwn(e, "kind")) return e.message;
|
|
63
|
+
let s = "";
|
|
64
|
+
if (e.plugin) s += `[plugin ${e.plugin}]`;
|
|
65
|
+
const id = e.id ?? e.loc?.file;
|
|
66
|
+
if (id) {
|
|
67
|
+
s += " " + id;
|
|
68
|
+
if (e.loc) s += `:${e.loc.line}:${e.loc.column}`;
|
|
69
|
+
}
|
|
70
|
+
if (s) s += "\n";
|
|
71
|
+
const message = `${e.name ?? "Error"}: ${e.message}`;
|
|
72
|
+
s += message;
|
|
73
|
+
if (e.frame) s = joinNewLine(s, e.frame);
|
|
74
|
+
if (e.stack) s = joinNewLine(s, e.stack.replace(message, ""));
|
|
75
|
+
if (e.cause) {
|
|
76
|
+
s = joinNewLine(s, "Caused by:");
|
|
77
|
+
s = joinNewLine(s, getErrorMessage(e.cause).split("\n").map((line) => " " + line).join("\n"));
|
|
78
|
+
}
|
|
79
|
+
return s;
|
|
80
|
+
}
|
|
81
|
+
function joinNewLine(s1, s2) {
|
|
82
|
+
return s1.replace(/\n+$/, "") + "\n" + s2.replace(/^\n+/, "");
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { bindingifySourcemap as a, unwrapBindingResult as i, normalizeBindingError as n, normalizeBindingResult as r, aggregateBindingErrorsIntoJsError as t };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { a as RolldownLog } from "./logging-xuHO4mAy.mjs";
|
|
2
|
+
//#region src/get-log-filter.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* @param filters A list of log filters to apply
|
|
5
|
+
* @returns A function that tests whether a log should be output
|
|
6
|
+
*
|
|
7
|
+
* @category Config
|
|
8
|
+
*/
|
|
9
|
+
type GetLogFilter = (filters: string[]) => (log: RolldownLog) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* A helper function to generate log filters using the same syntax as the CLI.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { defineConfig } from 'rolldown';
|
|
16
|
+
* import { getLogFilter } from 'rolldown/getLogFilter';
|
|
17
|
+
*
|
|
18
|
+
* const logFilter = getLogFilter(['code:FOO', 'code:BAR']);
|
|
19
|
+
*
|
|
20
|
+
* export default defineConfig({
|
|
21
|
+
* input: 'main.js',
|
|
22
|
+
* onLog(level, log, handler) {
|
|
23
|
+
* if (logFilter(log)) {
|
|
24
|
+
* handler(level, log);
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @category Config
|
|
31
|
+
*/
|
|
32
|
+
declare const getLogFilter: GetLogFilter;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { getLogFilter as n, GetLogFilter as t };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { t as rolldown } from "./rolldown-C9Hfg50O.mjs";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { readdir } from "node:fs/promises";
|
|
5
|
+
import { pathToFileURL } from "node:url";
|
|
6
|
+
import { cwd } from "node:process";
|
|
7
|
+
//#region src/utils/load-config.ts
|
|
8
|
+
async function bundleTsConfig(configFile, isEsm) {
|
|
9
|
+
const dirnameVarName = "injected_original_dirname";
|
|
10
|
+
const filenameVarName = "injected_original_filename";
|
|
11
|
+
const importMetaUrlVarName = "injected_original_import_meta_url";
|
|
12
|
+
const bundle = await rolldown({
|
|
13
|
+
input: configFile,
|
|
14
|
+
platform: "node",
|
|
15
|
+
resolve: { mainFields: ["main"] },
|
|
16
|
+
transform: { define: {
|
|
17
|
+
__dirname: dirnameVarName,
|
|
18
|
+
__filename: filenameVarName,
|
|
19
|
+
"import.meta.url": importMetaUrlVarName,
|
|
20
|
+
"import.meta.dirname": dirnameVarName,
|
|
21
|
+
"import.meta.filename": filenameVarName
|
|
22
|
+
} },
|
|
23
|
+
treeshake: false,
|
|
24
|
+
external: [/^[\w@][^:]/],
|
|
25
|
+
plugins: [{
|
|
26
|
+
name: "inject-file-scope-variables",
|
|
27
|
+
transform: {
|
|
28
|
+
filter: { id: /\.[cm]?[jt]s$/ },
|
|
29
|
+
async handler(code, id) {
|
|
30
|
+
return {
|
|
31
|
+
code: `const ${dirnameVarName} = ${JSON.stringify(path.dirname(id))};const ${filenameVarName} = ${JSON.stringify(id)};const ${importMetaUrlVarName} = ${JSON.stringify(pathToFileURL(id).href)};` + code,
|
|
32
|
+
map: null
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}]
|
|
37
|
+
});
|
|
38
|
+
const outputDir = path.dirname(configFile);
|
|
39
|
+
const fileName = (await bundle.write({
|
|
40
|
+
dir: outputDir,
|
|
41
|
+
format: isEsm ? "esm" : "cjs",
|
|
42
|
+
sourcemap: "inline",
|
|
43
|
+
entryFileNames: `rolldown.config.[hash]${path.extname(configFile).replace("ts", "js")}`
|
|
44
|
+
})).output.find((chunk) => chunk.type === "chunk" && chunk.isEntry).fileName;
|
|
45
|
+
return path.join(outputDir, fileName);
|
|
46
|
+
}
|
|
47
|
+
const SUPPORTED_JS_CONFIG_FORMATS = [
|
|
48
|
+
".js",
|
|
49
|
+
".mjs",
|
|
50
|
+
".cjs"
|
|
51
|
+
];
|
|
52
|
+
const SUPPORTED_TS_CONFIG_FORMATS = [
|
|
53
|
+
".ts",
|
|
54
|
+
".mts",
|
|
55
|
+
".cts"
|
|
56
|
+
];
|
|
57
|
+
const SUPPORTED_CONFIG_FORMATS = [...SUPPORTED_JS_CONFIG_FORMATS, ...SUPPORTED_TS_CONFIG_FORMATS];
|
|
58
|
+
const DEFAULT_CONFIG_BASE = "rolldown.config";
|
|
59
|
+
async function findConfigFileNameInCwd() {
|
|
60
|
+
const filesInWorkingDirectory = new Set(await readdir(cwd()));
|
|
61
|
+
for (const extension of SUPPORTED_CONFIG_FORMATS) {
|
|
62
|
+
const fileName = `${DEFAULT_CONFIG_BASE}${extension}`;
|
|
63
|
+
if (filesInWorkingDirectory.has(fileName)) return fileName;
|
|
64
|
+
}
|
|
65
|
+
throw new Error("No `rolldown.config` configuration file found.");
|
|
66
|
+
}
|
|
67
|
+
async function loadTsConfig(configFile) {
|
|
68
|
+
const file = await bundleTsConfig(configFile, isFilePathESM(configFile));
|
|
69
|
+
try {
|
|
70
|
+
return (await import(pathToFileURL(file).href)).default;
|
|
71
|
+
} finally {
|
|
72
|
+
fs.unlink(file, () => {});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function isFilePathESM(filePath) {
|
|
76
|
+
if (/\.m[jt]s$/.test(filePath)) return true;
|
|
77
|
+
else if (/\.c[jt]s$/.test(filePath)) return false;
|
|
78
|
+
else {
|
|
79
|
+
const pkg = findNearestPackageData(path.dirname(filePath));
|
|
80
|
+
if (pkg) return pkg.type === "module";
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function findNearestPackageData(basedir) {
|
|
85
|
+
while (basedir) {
|
|
86
|
+
const pkgPath = path.join(basedir, "package.json");
|
|
87
|
+
if (tryStatSync(pkgPath)?.isFile()) try {
|
|
88
|
+
return JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
89
|
+
} catch {}
|
|
90
|
+
const nextBasedir = path.dirname(basedir);
|
|
91
|
+
if (nextBasedir === basedir) break;
|
|
92
|
+
basedir = nextBasedir;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
function tryStatSync(file) {
|
|
97
|
+
try {
|
|
98
|
+
return fs.statSync(file, { throwIfNoEntry: false });
|
|
99
|
+
} catch {}
|
|
100
|
+
}
|
|
101
|
+
async function loadNativeConfig(resolvedPath) {
|
|
102
|
+
const url = pathToFileURL(resolvedPath).href;
|
|
103
|
+
const { freshImport } = await import("./dist-DKbukT1H.mjs");
|
|
104
|
+
const freshImported = freshImport(url);
|
|
105
|
+
if (freshImported) {
|
|
106
|
+
const { result } = await freshImported;
|
|
107
|
+
return result.default;
|
|
108
|
+
}
|
|
109
|
+
return (await import(url + "?t=" + Date.now())).default;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Load config from a file in a way that Rolldown does.
|
|
113
|
+
*
|
|
114
|
+
* @param configPath The path to the config file. If empty, it will look for `rolldown.config` with supported extensions in the current working directory.
|
|
115
|
+
* @param options Loading options. `configLoader` selects `'bundle'` (default) or `'native'`.
|
|
116
|
+
* @returns The loaded config export
|
|
117
|
+
*
|
|
118
|
+
* @category Config
|
|
119
|
+
*/
|
|
120
|
+
async function loadConfig(configPath, options = {}) {
|
|
121
|
+
const configLoader = options.configLoader ?? "bundle";
|
|
122
|
+
const ext = path.extname(configPath = configPath || await findConfigFileNameInCwd());
|
|
123
|
+
try {
|
|
124
|
+
if (configLoader === "native") return await loadNativeConfig(path.resolve(configPath));
|
|
125
|
+
if (SUPPORTED_JS_CONFIG_FORMATS.includes(ext) || process.env.NODE_OPTIONS?.includes("--import=tsx") && SUPPORTED_TS_CONFIG_FORMATS.includes(ext)) return (await import(pathToFileURL(configPath).href)).default;
|
|
126
|
+
else if (SUPPORTED_TS_CONFIG_FORMATS.includes(ext)) return await loadTsConfig(path.resolve(configPath));
|
|
127
|
+
else throw new Error(`Unsupported config format. Expected: \`${SUPPORTED_CONFIG_FORMATS.join(",")}\` but got \`${ext}\``);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
if (configLoader === "native") {
|
|
130
|
+
const tsHint = SUPPORTED_TS_CONFIG_FORMATS.includes(ext) && !process.features.typescript ? " This runtime does not natively support TypeScript config files." : "";
|
|
131
|
+
throw new Error(`Failed to load the config file "${configPath}" using the "native" config loader.${tsHint} Try "--configLoader bundle", or register a loader such as "--import tsx".`, { cause: err });
|
|
132
|
+
}
|
|
133
|
+
throw new Error("Error happened while loading config.", { cause: err });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
export { loadConfig as t };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/log/logging.d.ts
|
|
2
|
+
/** @inline */
|
|
3
|
+
type LogLevel = "info" | "debug" | "warn";
|
|
4
|
+
/** @inline */
|
|
5
|
+
type LogLevelOption = LogLevel | "silent";
|
|
6
|
+
/** @inline */
|
|
7
|
+
type LogLevelWithError = LogLevel | "error";
|
|
8
|
+
interface RolldownLog {
|
|
9
|
+
binding?: string;
|
|
10
|
+
cause?: unknown;
|
|
11
|
+
/**
|
|
12
|
+
* The log code for this log object.
|
|
13
|
+
* @example 'PLUGIN_ERROR'
|
|
14
|
+
*/
|
|
15
|
+
code?: string;
|
|
16
|
+
exporter?: string;
|
|
17
|
+
frame?: string;
|
|
18
|
+
hook?: string;
|
|
19
|
+
id?: string;
|
|
20
|
+
ids?: string[];
|
|
21
|
+
loc?: {
|
|
22
|
+
column: number;
|
|
23
|
+
file?: string;
|
|
24
|
+
line: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The message for this log object.
|
|
28
|
+
* @example 'The "transform" hook used by the output plugin "rolldown-plugin-foo" is a build time hook and will not be run for that plugin. Either this plugin cannot be used as an output plugin, or it should have an option to configure it as an output plugin.'
|
|
29
|
+
*/
|
|
30
|
+
message: string;
|
|
31
|
+
meta?: any;
|
|
32
|
+
names?: string[];
|
|
33
|
+
plugin?: string;
|
|
34
|
+
pluginCode?: unknown;
|
|
35
|
+
pos?: number;
|
|
36
|
+
reexporter?: string;
|
|
37
|
+
stack?: string;
|
|
38
|
+
url?: string;
|
|
39
|
+
}
|
|
40
|
+
/** @inline */
|
|
41
|
+
type RolldownLogWithString = RolldownLog | string;
|
|
42
|
+
/** @category Plugin APIs */
|
|
43
|
+
interface RolldownError extends RolldownLog {
|
|
44
|
+
name?: string;
|
|
45
|
+
stack?: string;
|
|
46
|
+
watchFiles?: string[];
|
|
47
|
+
}
|
|
48
|
+
type LogOrStringHandler = (level: LogLevelWithError, log: RolldownLogWithString) => void;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { RolldownLog as a, RolldownError as i, LogLevelOption as n, RolldownLogWithString as o, LogOrStringHandler as r, LogLevel as t };
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
//#region src/utils/code-frame.ts
|
|
2
|
+
function spaces(index) {
|
|
3
|
+
let result = "";
|
|
4
|
+
while (index--) result += " ";
|
|
5
|
+
return result;
|
|
6
|
+
}
|
|
7
|
+
function tabsToSpaces(value) {
|
|
8
|
+
return value.replace(/^\t+/, (match) => match.split(" ").join(" "));
|
|
9
|
+
}
|
|
10
|
+
const LINE_TRUNCATE_LENGTH = 120;
|
|
11
|
+
const MIN_CHARACTERS_SHOWN_AFTER_LOCATION = 10;
|
|
12
|
+
const ELLIPSIS = "...";
|
|
13
|
+
function getCodeFrame(source, line, column) {
|
|
14
|
+
let lines = source.split("\n");
|
|
15
|
+
if (line > lines.length) return "";
|
|
16
|
+
const maxLineLength = Math.max(tabsToSpaces(lines[line - 1].slice(0, column)).length + MIN_CHARACTERS_SHOWN_AFTER_LOCATION + 3, LINE_TRUNCATE_LENGTH);
|
|
17
|
+
const frameStart = Math.max(0, line - 3);
|
|
18
|
+
let frameEnd = Math.min(line + 2, lines.length);
|
|
19
|
+
lines = lines.slice(frameStart, frameEnd);
|
|
20
|
+
while (!/\S/.test(lines[lines.length - 1])) {
|
|
21
|
+
lines.pop();
|
|
22
|
+
frameEnd -= 1;
|
|
23
|
+
}
|
|
24
|
+
const digits = String(frameEnd).length;
|
|
25
|
+
return lines.map((sourceLine, index) => {
|
|
26
|
+
const isErrorLine = frameStart + index + 1 === line;
|
|
27
|
+
let lineNumber = String(index + frameStart + 1);
|
|
28
|
+
while (lineNumber.length < digits) lineNumber = ` ${lineNumber}`;
|
|
29
|
+
let displayedLine = tabsToSpaces(sourceLine);
|
|
30
|
+
if (displayedLine.length > maxLineLength) displayedLine = `${displayedLine.slice(0, maxLineLength - 3)}${ELLIPSIS}`;
|
|
31
|
+
if (isErrorLine) {
|
|
32
|
+
const indicator = spaces(digits + 2 + tabsToSpaces(sourceLine.slice(0, column)).length) + "^";
|
|
33
|
+
return `${lineNumber}: ${displayedLine}\n${indicator}`;
|
|
34
|
+
}
|
|
35
|
+
return `${lineNumber}: ${displayedLine}`;
|
|
36
|
+
}).join("\n");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/log/locate-character/index.js
|
|
40
|
+
/** @typedef {import('./types').Location} Location */
|
|
41
|
+
/**
|
|
42
|
+
* @param {import('./types').Range} range
|
|
43
|
+
* @param {number} index
|
|
44
|
+
*/
|
|
45
|
+
function rangeContains(range, index) {
|
|
46
|
+
return range.start <= index && index < range.end;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @param {string} source
|
|
50
|
+
* @param {import('./types').Options} [options]
|
|
51
|
+
*/
|
|
52
|
+
function getLocator(source, options = {}) {
|
|
53
|
+
const { offsetLine = 0, offsetColumn = 0 } = options;
|
|
54
|
+
let start = 0;
|
|
55
|
+
const ranges = source.split("\n").map((line, i) => {
|
|
56
|
+
const end = start + line.length + 1;
|
|
57
|
+
/** @type {import('./types').Range} */
|
|
58
|
+
const range = {
|
|
59
|
+
start,
|
|
60
|
+
end,
|
|
61
|
+
line: i
|
|
62
|
+
};
|
|
63
|
+
start = end;
|
|
64
|
+
return range;
|
|
65
|
+
});
|
|
66
|
+
let i = 0;
|
|
67
|
+
/**
|
|
68
|
+
* @param {string | number} search
|
|
69
|
+
* @param {number} [index]
|
|
70
|
+
* @returns {Location | undefined}
|
|
71
|
+
*/
|
|
72
|
+
function locator(search, index) {
|
|
73
|
+
if (typeof search === "string") search = source.indexOf(search, index ?? 0);
|
|
74
|
+
if (search === -1) return void 0;
|
|
75
|
+
let range = ranges[i];
|
|
76
|
+
const d = search >= range.end ? 1 : -1;
|
|
77
|
+
while (range) {
|
|
78
|
+
if (rangeContains(range, search)) return {
|
|
79
|
+
line: offsetLine + range.line,
|
|
80
|
+
column: offsetColumn + search - range.start,
|
|
81
|
+
character: search
|
|
82
|
+
};
|
|
83
|
+
i += d;
|
|
84
|
+
range = ranges[i];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return locator;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} source
|
|
91
|
+
* @param {string | number} search
|
|
92
|
+
* @param {import('./types').Options} [options]
|
|
93
|
+
* @returns {Location | undefined}
|
|
94
|
+
*/
|
|
95
|
+
function locate(source, search, options) {
|
|
96
|
+
return getLocator(source, options)(search, options && options.startIndex);
|
|
97
|
+
}
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/log/logs.ts
|
|
100
|
+
const INVALID_LOG_POSITION = "INVALID_LOG_POSITION";
|
|
101
|
+
const PLUGIN_ERROR = "PLUGIN_ERROR";
|
|
102
|
+
const INPUT_HOOK_IN_OUTPUT_PLUGIN = "INPUT_HOOK_IN_OUTPUT_PLUGIN";
|
|
103
|
+
const CYCLE_LOADING = "CYCLE_LOADING";
|
|
104
|
+
const MULTIPLE_WATCHER_OPTION = "MULTIPLE_WATCHER_OPTION";
|
|
105
|
+
const PARSE_ERROR = "PARSE_ERROR";
|
|
106
|
+
const VALIDATION_ERROR = "VALIDATION_ERROR";
|
|
107
|
+
function logParseError(message, id, pos) {
|
|
108
|
+
return {
|
|
109
|
+
code: PARSE_ERROR,
|
|
110
|
+
id,
|
|
111
|
+
message,
|
|
112
|
+
pos
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function logFailedValidation(message) {
|
|
116
|
+
return {
|
|
117
|
+
code: VALIDATION_ERROR,
|
|
118
|
+
message
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function logInvalidLogPosition(pluginName) {
|
|
122
|
+
return {
|
|
123
|
+
code: INVALID_LOG_POSITION,
|
|
124
|
+
message: `Plugin "${pluginName}" tried to add a file position to a log or warning. This is only supported in the "transform" hook at the moment and will be ignored.`
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function logInputHookInOutputPlugin(pluginName, hookName) {
|
|
128
|
+
return {
|
|
129
|
+
code: INPUT_HOOK_IN_OUTPUT_PLUGIN,
|
|
130
|
+
message: `The "${hookName}" hook used by the output plugin ${pluginName} is a build time hook and will not be run for that plugin. Either this plugin cannot be used as an output plugin, or it should have an option to configure it as an output plugin.`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function logCycleLoading(pluginName, moduleId) {
|
|
134
|
+
return {
|
|
135
|
+
code: CYCLE_LOADING,
|
|
136
|
+
message: `Found the module "${moduleId}" cycle loading at ${pluginName} plugin, it maybe blocking fetching modules.`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function logMultipleWatcherOption() {
|
|
140
|
+
return {
|
|
141
|
+
code: MULTIPLE_WATCHER_OPTION,
|
|
142
|
+
message: `Found multiple watcher options at watch options, using first one to start watcher.`
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function logPluginError(error, plugin, { hook, id } = {}) {
|
|
146
|
+
try {
|
|
147
|
+
const code = error.code;
|
|
148
|
+
if (!error.pluginCode && code != null && (typeof code !== "string" || !code.startsWith("PLUGIN_"))) error.pluginCode = code;
|
|
149
|
+
error.code = PLUGIN_ERROR;
|
|
150
|
+
error.plugin = plugin;
|
|
151
|
+
if (hook) error.hook = hook;
|
|
152
|
+
if (id) error.id = id;
|
|
153
|
+
} catch (_) {} finally {
|
|
154
|
+
return error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function error(base) {
|
|
158
|
+
if (!(base instanceof Error)) {
|
|
159
|
+
base = Object.assign(new Error(base.message), base);
|
|
160
|
+
Object.defineProperty(base, "name", {
|
|
161
|
+
value: "RolldownError",
|
|
162
|
+
writable: true
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
throw base;
|
|
166
|
+
}
|
|
167
|
+
function augmentCodeLocation(properties, pos, source, id) {
|
|
168
|
+
if (typeof pos === "object") {
|
|
169
|
+
const { line, column } = pos;
|
|
170
|
+
properties.loc = {
|
|
171
|
+
column,
|
|
172
|
+
file: id,
|
|
173
|
+
line
|
|
174
|
+
};
|
|
175
|
+
} else {
|
|
176
|
+
properties.pos = pos;
|
|
177
|
+
const location = locate(source, pos, { offsetLine: 1 });
|
|
178
|
+
if (!location) return;
|
|
179
|
+
const { line, column } = location;
|
|
180
|
+
properties.loc = {
|
|
181
|
+
column,
|
|
182
|
+
file: id,
|
|
183
|
+
line
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (properties.frame === void 0) {
|
|
187
|
+
const { line, column } = properties.loc;
|
|
188
|
+
properties.frame = getCodeFrame(source, line, column);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
export { logInputHookInOutputPlugin as a, logParseError as c, getCodeFrame as d, logFailedValidation as i, logPluginError as l, error as n, logInvalidLogPosition as o, logCycleLoading as r, logMultipleWatcherOption as s, augmentCodeLocation as t, locate as u };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/utils/misc.ts
|
|
2
|
+
function arraify(value) {
|
|
3
|
+
return Array.isArray(value) ? value : [value];
|
|
4
|
+
}
|
|
5
|
+
function isPromiseLike(value) {
|
|
6
|
+
return value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
7
|
+
}
|
|
8
|
+
function unimplemented(info) {
|
|
9
|
+
if (info) throw new Error(`unimplemented: ${info}`);
|
|
10
|
+
throw new Error("unimplemented");
|
|
11
|
+
}
|
|
12
|
+
function unreachable(info) {
|
|
13
|
+
if (info) throw new Error(`unreachable: ${info}`);
|
|
14
|
+
throw new Error("unreachable");
|
|
15
|
+
}
|
|
16
|
+
function unsupported(info) {
|
|
17
|
+
throw new Error(`UNSUPPORTED: ${info}`);
|
|
18
|
+
}
|
|
19
|
+
function noop(..._args) {}
|
|
20
|
+
const ABSOLUTE_PATH_REGEX = /^(?:\/|(?:[A-Za-z]:)?[/\\|])/;
|
|
21
|
+
/**
|
|
22
|
+
* Whether `name` is a path fragment — an absolute or relative path. Emitted file
|
|
23
|
+
* names, `[name]` substitutions and file-name patterns can be neither.
|
|
24
|
+
*/
|
|
25
|
+
function isPathFragment(name) {
|
|
26
|
+
return name[0] === "/" || name[0] === "." && (name[1] === "/" || name[1] === ".") || ABSOLUTE_PATH_REGEX.test(name);
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { unimplemented as a, noop as i, isPathFragment as n, unreachable as o, isPromiseLike as r, unsupported as s, arraify as t };
|