@run0/jiki 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/dist/browser-bundle.d.ts +40 -0
- package/dist/builtins.d.ts +22 -0
- package/dist/code-transform.d.ts +7 -0
- package/dist/config/cdn.d.ts +13 -0
- package/dist/container.d.ts +101 -0
- package/dist/dev-server.d.ts +69 -0
- package/dist/errors.d.ts +19 -0
- package/dist/frameworks/code-transforms.d.ts +32 -0
- package/dist/frameworks/next-api-handler.d.ts +72 -0
- package/dist/frameworks/next-dev-server.d.ts +141 -0
- package/dist/frameworks/next-html-generator.d.ts +36 -0
- package/dist/frameworks/next-route-resolver.d.ts +19 -0
- package/dist/frameworks/next-shims.d.ts +78 -0
- package/dist/frameworks/remix-dev-server.d.ts +47 -0
- package/dist/frameworks/sveltekit-dev-server.d.ts +43 -0
- package/dist/frameworks/vite-dev-server.d.ts +50 -0
- package/dist/fs-errors.d.ts +36 -0
- package/dist/index.cjs +14916 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.mjs +14898 -0
- package/dist/index.mjs.map +1 -0
- package/dist/kernel.d.ts +48 -0
- package/dist/memfs.d.ts +144 -0
- package/dist/metrics.d.ts +78 -0
- package/dist/module-resolver.d.ts +60 -0
- package/dist/network-interceptor.d.ts +71 -0
- package/dist/npm/cache.d.ts +76 -0
- package/dist/npm/index.d.ts +60 -0
- package/dist/npm/lockfile-reader.d.ts +32 -0
- package/dist/npm/pnpm.d.ts +18 -0
- package/dist/npm/registry.d.ts +45 -0
- package/dist/npm/resolver.d.ts +39 -0
- package/dist/npm/sync-installer.d.ts +18 -0
- package/dist/npm/tarball.d.ts +4 -0
- package/dist/npm/workspaces.d.ts +46 -0
- package/dist/persistence.d.ts +94 -0
- package/dist/plugin.d.ts +156 -0
- package/dist/polyfills/assert.d.ts +30 -0
- package/dist/polyfills/child_process.d.ts +116 -0
- package/dist/polyfills/chokidar.d.ts +18 -0
- package/dist/polyfills/crypto.d.ts +49 -0
- package/dist/polyfills/events.d.ts +28 -0
- package/dist/polyfills/fs.d.ts +82 -0
- package/dist/polyfills/http.d.ts +147 -0
- package/dist/polyfills/module.d.ts +29 -0
- package/dist/polyfills/net.d.ts +53 -0
- package/dist/polyfills/os.d.ts +91 -0
- package/dist/polyfills/path.d.ts +96 -0
- package/dist/polyfills/perf_hooks.d.ts +21 -0
- package/dist/polyfills/process.d.ts +99 -0
- package/dist/polyfills/querystring.d.ts +15 -0
- package/dist/polyfills/readdirp.d.ts +18 -0
- package/dist/polyfills/readline.d.ts +32 -0
- package/dist/polyfills/stream.d.ts +106 -0
- package/dist/polyfills/stubs.d.ts +737 -0
- package/dist/polyfills/tty.d.ts +25 -0
- package/dist/polyfills/url.d.ts +41 -0
- package/dist/polyfills/util.d.ts +61 -0
- package/dist/polyfills/v8.d.ts +43 -0
- package/dist/polyfills/vm.d.ts +76 -0
- package/dist/polyfills/worker-threads.d.ts +77 -0
- package/dist/polyfills/ws.d.ts +32 -0
- package/dist/polyfills/zlib.d.ts +87 -0
- package/dist/runtime-helpers.d.ts +4 -0
- package/dist/runtime-interface.d.ts +39 -0
- package/dist/sandbox.d.ts +69 -0
- package/dist/server-bridge.d.ts +55 -0
- package/dist/shell-commands.d.ts +2 -0
- package/dist/shell.d.ts +101 -0
- package/dist/transpiler.d.ts +47 -0
- package/dist/type-checker.d.ts +57 -0
- package/dist/types/package-json.d.ts +17 -0
- package/dist/utils/binary-encoding.d.ts +4 -0
- package/dist/utils/hash.d.ts +6 -0
- package/dist/utils/safe-path.d.ts +6 -0
- package/dist/worker-runtime.d.ts +34 -0
- package/package.json +59 -0
- package/src/browser-bundle.ts +498 -0
- package/src/builtins.ts +222 -0
- package/src/code-transform.ts +183 -0
- package/src/config/cdn.ts +17 -0
- package/src/container.ts +343 -0
- package/src/dev-server.ts +322 -0
- package/src/errors.ts +604 -0
- package/src/frameworks/code-transforms.ts +667 -0
- package/src/frameworks/next-api-handler.ts +366 -0
- package/src/frameworks/next-dev-server.ts +1252 -0
- package/src/frameworks/next-html-generator.ts +585 -0
- package/src/frameworks/next-route-resolver.ts +521 -0
- package/src/frameworks/next-shims.ts +1084 -0
- package/src/frameworks/remix-dev-server.ts +163 -0
- package/src/frameworks/sveltekit-dev-server.ts +197 -0
- package/src/frameworks/vite-dev-server.ts +370 -0
- package/src/fs-errors.ts +118 -0
- package/src/index.ts +188 -0
- package/src/kernel.ts +381 -0
- package/src/memfs.ts +1006 -0
- package/src/metrics.ts +140 -0
- package/src/module-resolver.ts +511 -0
- package/src/network-interceptor.ts +143 -0
- package/src/npm/cache.ts +172 -0
- package/src/npm/index.ts +377 -0
- package/src/npm/lockfile-reader.ts +105 -0
- package/src/npm/pnpm.ts +108 -0
- package/src/npm/registry.ts +120 -0
- package/src/npm/resolver.ts +339 -0
- package/src/npm/sync-installer.ts +217 -0
- package/src/npm/tarball.ts +136 -0
- package/src/npm/workspaces.ts +255 -0
- package/src/persistence.ts +235 -0
- package/src/plugin.ts +293 -0
- package/src/polyfills/assert.ts +164 -0
- package/src/polyfills/child_process.ts +535 -0
- package/src/polyfills/chokidar.ts +52 -0
- package/src/polyfills/crypto.ts +433 -0
- package/src/polyfills/events.ts +178 -0
- package/src/polyfills/fs.ts +297 -0
- package/src/polyfills/http.ts +478 -0
- package/src/polyfills/module.ts +97 -0
- package/src/polyfills/net.ts +123 -0
- package/src/polyfills/os.ts +108 -0
- package/src/polyfills/path.ts +169 -0
- package/src/polyfills/perf_hooks.ts +30 -0
- package/src/polyfills/process.ts +349 -0
- package/src/polyfills/querystring.ts +66 -0
- package/src/polyfills/readdirp.ts +72 -0
- package/src/polyfills/readline.ts +80 -0
- package/src/polyfills/stream.ts +610 -0
- package/src/polyfills/stubs.ts +600 -0
- package/src/polyfills/tty.ts +43 -0
- package/src/polyfills/url.ts +97 -0
- package/src/polyfills/util.ts +173 -0
- package/src/polyfills/v8.ts +62 -0
- package/src/polyfills/vm.ts +111 -0
- package/src/polyfills/worker-threads.ts +189 -0
- package/src/polyfills/ws.ts +73 -0
- package/src/polyfills/zlib.ts +244 -0
- package/src/runtime-helpers.ts +83 -0
- package/src/runtime-interface.ts +46 -0
- package/src/sandbox.ts +178 -0
- package/src/server-bridge.ts +473 -0
- package/src/service-worker.ts +153 -0
- package/src/shell-commands.ts +708 -0
- package/src/shell.ts +795 -0
- package/src/transpiler.ts +282 -0
- package/src/type-checker.ts +241 -0
- package/src/types/package-json.ts +17 -0
- package/src/utils/binary-encoding.ts +38 -0
- package/src/utils/hash.ts +24 -0
- package/src/utils/safe-path.ts +38 -0
- package/src/worker-runtime.ts +42 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export const URL = globalThis.URL;
|
|
2
|
+
export const URLSearchParams = globalThis.URLSearchParams;
|
|
3
|
+
|
|
4
|
+
export function parse(
|
|
5
|
+
urlString: string,
|
|
6
|
+
parseQueryString = false,
|
|
7
|
+
slashesDenoteHost = false,
|
|
8
|
+
): Record<string, unknown> {
|
|
9
|
+
try {
|
|
10
|
+
const parsed = new globalThis.URL(urlString, "http://localhost");
|
|
11
|
+
const result: Record<string, unknown> = {
|
|
12
|
+
protocol: parsed.protocol,
|
|
13
|
+
slashes: parsed.protocol ? true : null,
|
|
14
|
+
auth: parsed.username
|
|
15
|
+
? parsed.password
|
|
16
|
+
? `${parsed.username}:${parsed.password}`
|
|
17
|
+
: parsed.username
|
|
18
|
+
: null,
|
|
19
|
+
host: parsed.host,
|
|
20
|
+
port: parsed.port || null,
|
|
21
|
+
hostname: parsed.hostname,
|
|
22
|
+
hash: parsed.hash || null,
|
|
23
|
+
search: parsed.search || null,
|
|
24
|
+
query: parseQueryString
|
|
25
|
+
? Object.fromEntries(parsed.searchParams)
|
|
26
|
+
: parsed.search?.slice(1) || null,
|
|
27
|
+
pathname: parsed.pathname,
|
|
28
|
+
path: parsed.pathname + (parsed.search || ""),
|
|
29
|
+
href: parsed.href,
|
|
30
|
+
};
|
|
31
|
+
return result;
|
|
32
|
+
} catch {
|
|
33
|
+
return {
|
|
34
|
+
protocol: null,
|
|
35
|
+
slashes: null,
|
|
36
|
+
auth: null,
|
|
37
|
+
host: null,
|
|
38
|
+
port: null,
|
|
39
|
+
hostname: null,
|
|
40
|
+
hash: null,
|
|
41
|
+
search: null,
|
|
42
|
+
query: null,
|
|
43
|
+
pathname: urlString,
|
|
44
|
+
path: urlString,
|
|
45
|
+
href: urlString,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function format(urlObj: Record<string, unknown>): string {
|
|
51
|
+
if (typeof urlObj === "string") return urlObj;
|
|
52
|
+
let result = "";
|
|
53
|
+
if (urlObj.protocol) result += urlObj.protocol;
|
|
54
|
+
if (urlObj.slashes) result += "//";
|
|
55
|
+
if (urlObj.auth) result += urlObj.auth + "@";
|
|
56
|
+
if (urlObj.hostname) result += urlObj.hostname;
|
|
57
|
+
if (urlObj.port) result += ":" + urlObj.port;
|
|
58
|
+
if (urlObj.pathname) result += urlObj.pathname;
|
|
59
|
+
if (urlObj.search) result += urlObj.search;
|
|
60
|
+
if (urlObj.hash) result += urlObj.hash;
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function resolve(from: string, to: string): string {
|
|
65
|
+
return new globalThis.URL(to, from).href;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function fileURLToPath(url: string | URL): string {
|
|
69
|
+
const urlStr = typeof url === "string" ? url : url.href;
|
|
70
|
+
if (!urlStr.startsWith("file://")) throw new Error("Invalid file URL");
|
|
71
|
+
return decodeURIComponent(urlStr.replace(/^file:\/\//, ""));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function pathToFileURL(path: string): URL {
|
|
75
|
+
return new globalThis.URL(
|
|
76
|
+
"file://" + encodeURIComponent(path).replace(/%2F/g, "/"),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function domainToASCII(domain: string): string {
|
|
81
|
+
return domain;
|
|
82
|
+
}
|
|
83
|
+
export function domainToUnicode(domain: string): string {
|
|
84
|
+
return domain;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
URL,
|
|
89
|
+
URLSearchParams,
|
|
90
|
+
parse,
|
|
91
|
+
format,
|
|
92
|
+
resolve,
|
|
93
|
+
fileURLToPath,
|
|
94
|
+
pathToFileURL,
|
|
95
|
+
domainToASCII,
|
|
96
|
+
domainToUnicode,
|
|
97
|
+
};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
export function format(fmt: unknown, ...args: unknown[]): string {
|
|
2
|
+
if (typeof fmt !== "string")
|
|
3
|
+
return args.length
|
|
4
|
+
? [fmt, ...args].map(a => inspect(a)).join(" ")
|
|
5
|
+
: inspect(fmt);
|
|
6
|
+
let i = 0;
|
|
7
|
+
return fmt.replace(/%[sdjifoO%]/g, m => {
|
|
8
|
+
if (m === "%%") return "%";
|
|
9
|
+
if (i >= args.length) return m;
|
|
10
|
+
const arg = args[i++];
|
|
11
|
+
switch (m) {
|
|
12
|
+
case "%s":
|
|
13
|
+
return String(arg);
|
|
14
|
+
case "%d":
|
|
15
|
+
return String(Number(arg));
|
|
16
|
+
case "%i":
|
|
17
|
+
return String(Math.floor(Number(arg)));
|
|
18
|
+
case "%f":
|
|
19
|
+
return String(parseFloat(String(arg)));
|
|
20
|
+
case "%j":
|
|
21
|
+
try {
|
|
22
|
+
return JSON.stringify(arg);
|
|
23
|
+
} catch {
|
|
24
|
+
return "[Circular]";
|
|
25
|
+
}
|
|
26
|
+
case "%o":
|
|
27
|
+
case "%O":
|
|
28
|
+
return inspect(arg);
|
|
29
|
+
default:
|
|
30
|
+
return m;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function inspect(
|
|
36
|
+
obj: unknown,
|
|
37
|
+
opts?: { depth?: number; colors?: boolean },
|
|
38
|
+
): string {
|
|
39
|
+
if (obj === null) return "null";
|
|
40
|
+
if (obj === undefined) return "undefined";
|
|
41
|
+
if (typeof obj === "string") return `'${obj}'`;
|
|
42
|
+
if (
|
|
43
|
+
typeof obj === "number" ||
|
|
44
|
+
typeof obj === "boolean" ||
|
|
45
|
+
typeof obj === "bigint"
|
|
46
|
+
)
|
|
47
|
+
return String(obj);
|
|
48
|
+
if (typeof obj === "function")
|
|
49
|
+
return `[Function: ${obj.name || "anonymous"}]`;
|
|
50
|
+
if (typeof obj === "symbol") return obj.toString();
|
|
51
|
+
if (obj instanceof Date) return obj.toISOString();
|
|
52
|
+
if (obj instanceof RegExp) return obj.toString();
|
|
53
|
+
if (obj instanceof Error) return `${obj.name}: ${obj.message}`;
|
|
54
|
+
if (Array.isArray(obj)) return `[ ${obj.map(v => inspect(v)).join(", ")} ]`;
|
|
55
|
+
if (obj instanceof Map)
|
|
56
|
+
return `Map(${obj.size}) { ${[...obj.entries()]
|
|
57
|
+
.map(([k, v]) => `${inspect(k)} => ${inspect(v)}`)
|
|
58
|
+
.join(", ")} }`;
|
|
59
|
+
if (obj instanceof Set)
|
|
60
|
+
return `Set(${obj.size}) { ${[...obj].map(v => inspect(v)).join(", ")} }`;
|
|
61
|
+
try {
|
|
62
|
+
return JSON.stringify(obj, null, 2);
|
|
63
|
+
} catch {
|
|
64
|
+
return "[Object]";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
inspect.custom = Symbol.for("nodejs.util.inspect.custom");
|
|
68
|
+
|
|
69
|
+
export function inherits(ctor: Function, superCtor: Function): void {
|
|
70
|
+
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
|
|
71
|
+
Object.setPrototypeOf(ctor, superCtor);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function deprecate<T extends Function>(fn: T, msg: string): T {
|
|
75
|
+
let warned = false;
|
|
76
|
+
return function (this: unknown, ...args: unknown[]) {
|
|
77
|
+
if (!warned) {
|
|
78
|
+
console.warn("DeprecationWarning:", msg);
|
|
79
|
+
warned = true;
|
|
80
|
+
}
|
|
81
|
+
return fn.apply(this, args);
|
|
82
|
+
} as unknown as T;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function promisify<T extends Function>(
|
|
86
|
+
fn: T,
|
|
87
|
+
): (...args: unknown[]) => Promise<unknown> {
|
|
88
|
+
return (...args: unknown[]) =>
|
|
89
|
+
new Promise((resolve, reject) => {
|
|
90
|
+
fn(...args, (err: Error | null, ...result: unknown[]) => {
|
|
91
|
+
if (err) reject(err);
|
|
92
|
+
else resolve(result.length <= 1 ? result[0] : result);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function callbackify(
|
|
98
|
+
fn: (...args: unknown[]) => Promise<unknown>,
|
|
99
|
+
): (...args: unknown[]) => void {
|
|
100
|
+
return (...args: unknown[]) => {
|
|
101
|
+
const cb = args.pop() as Function;
|
|
102
|
+
fn(...args)
|
|
103
|
+
.then(result => cb(null, result))
|
|
104
|
+
.catch(err => cb(err));
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function debuglog(section: string): (...args: unknown[]) => void {
|
|
109
|
+
const enabled =
|
|
110
|
+
typeof process !== "undefined" &&
|
|
111
|
+
process.env?.NODE_DEBUG?.includes(section);
|
|
112
|
+
return enabled
|
|
113
|
+
? (...args) =>
|
|
114
|
+
console.error(`${section.toUpperCase()} ${process?.pid || 0}:`, ...args)
|
|
115
|
+
: () => {};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function isDeepStrictEqual(a: unknown, b: unknown): boolean {
|
|
119
|
+
if (a === b) return true;
|
|
120
|
+
if (typeof a !== typeof b) return false;
|
|
121
|
+
if (a === null || b === null) return false;
|
|
122
|
+
if (typeof a !== "object") return false;
|
|
123
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
124
|
+
if (a.length !== b.length) return false;
|
|
125
|
+
return a.every((v, i) => isDeepStrictEqual(v, b[i]));
|
|
126
|
+
}
|
|
127
|
+
const keysA = Object.keys(a as object);
|
|
128
|
+
const keysB = Object.keys(b as object);
|
|
129
|
+
if (keysA.length !== keysB.length) return false;
|
|
130
|
+
return keysA.every(k =>
|
|
131
|
+
isDeepStrictEqual(
|
|
132
|
+
(a as Record<string, unknown>)[k],
|
|
133
|
+
(b as Record<string, unknown>)[k],
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const types = {
|
|
139
|
+
isDate: (v: unknown): v is Date => v instanceof Date,
|
|
140
|
+
isRegExp: (v: unknown): v is RegExp => v instanceof RegExp,
|
|
141
|
+
isPromise: (v: unknown): v is Promise<unknown> => v instanceof Promise,
|
|
142
|
+
isMap: (v: unknown): v is Map<unknown, unknown> => v instanceof Map,
|
|
143
|
+
isSet: (v: unknown): v is Set<unknown> => v instanceof Set,
|
|
144
|
+
isTypedArray: (v: unknown): boolean =>
|
|
145
|
+
ArrayBuffer.isView(v) && !(v instanceof DataView),
|
|
146
|
+
isUint8Array: (v: unknown): v is Uint8Array => v instanceof Uint8Array,
|
|
147
|
+
isArrayBuffer: (v: unknown): v is ArrayBuffer => v instanceof ArrayBuffer,
|
|
148
|
+
isSharedArrayBuffer: (v: unknown): boolean =>
|
|
149
|
+
typeof SharedArrayBuffer !== "undefined" && v instanceof SharedArrayBuffer,
|
|
150
|
+
isProxy: (_v: unknown): boolean => false,
|
|
151
|
+
isNativeError: (v: unknown): v is Error => v instanceof Error,
|
|
152
|
+
isGeneratorFunction: (v: unknown): boolean =>
|
|
153
|
+
typeof v === "function" && v.constructor?.name === "GeneratorFunction",
|
|
154
|
+
isAsyncFunction: (v: unknown): boolean =>
|
|
155
|
+
typeof v === "function" && v.constructor?.name === "AsyncFunction",
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export class TextEncoder extends globalThis.TextEncoder {}
|
|
159
|
+
export class TextDecoder extends globalThis.TextDecoder {}
|
|
160
|
+
|
|
161
|
+
export default {
|
|
162
|
+
format,
|
|
163
|
+
inspect,
|
|
164
|
+
inherits,
|
|
165
|
+
deprecate,
|
|
166
|
+
promisify,
|
|
167
|
+
callbackify,
|
|
168
|
+
debuglog,
|
|
169
|
+
isDeepStrictEqual,
|
|
170
|
+
types,
|
|
171
|
+
TextEncoder,
|
|
172
|
+
TextDecoder,
|
|
173
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export function getHeapStatistics(): Record<string, number> {
|
|
2
|
+
return {
|
|
3
|
+
total_heap_size: 30 * 1024 * 1024,
|
|
4
|
+
used_heap_size: 20 * 1024 * 1024,
|
|
5
|
+
heap_size_limit: 512 * 1024 * 1024,
|
|
6
|
+
total_physical_size: 30 * 1024 * 1024,
|
|
7
|
+
total_available_size: 400 * 1024 * 1024,
|
|
8
|
+
malloced_memory: 0,
|
|
9
|
+
peak_malloced_memory: 0,
|
|
10
|
+
does_zap_garbage: 0,
|
|
11
|
+
number_of_native_contexts: 1,
|
|
12
|
+
number_of_detached_contexts: 0,
|
|
13
|
+
total_global_handles_size: 0,
|
|
14
|
+
used_global_handles_size: 0,
|
|
15
|
+
external_memory: 0,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function getHeapSpaceStatistics(): Record<string, unknown>[] {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
export function getHeapSnapshot(): unknown {
|
|
22
|
+
return {
|
|
23
|
+
toString() {
|
|
24
|
+
return "{}";
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function writeHeapSnapshot(_filename?: string): string {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
export function setFlagsFromString(_flags: string): void {}
|
|
32
|
+
export function serialize(value: unknown): Uint8Array {
|
|
33
|
+
return new TextEncoder().encode(JSON.stringify(value));
|
|
34
|
+
}
|
|
35
|
+
export function deserialize(buffer: Uint8Array): unknown {
|
|
36
|
+
return JSON.parse(new TextDecoder().decode(buffer));
|
|
37
|
+
}
|
|
38
|
+
export const DefaultSerializer = class {
|
|
39
|
+
writeHeader() {}
|
|
40
|
+
writeValue(_v: unknown) {}
|
|
41
|
+
releaseBuffer() {
|
|
42
|
+
return new Uint8Array(0);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export const DefaultDeserializer = class {
|
|
46
|
+
constructor(_buf: Uint8Array) {}
|
|
47
|
+
readHeader() {}
|
|
48
|
+
readValue() {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
export default {
|
|
53
|
+
getHeapStatistics,
|
|
54
|
+
getHeapSpaceStatistics,
|
|
55
|
+
getHeapSnapshot,
|
|
56
|
+
writeHeapSnapshot,
|
|
57
|
+
setFlagsFromString,
|
|
58
|
+
serialize,
|
|
59
|
+
deserialize,
|
|
60
|
+
DefaultSerializer,
|
|
61
|
+
DefaultDeserializer,
|
|
62
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser polyfill for Node.js `vm` module.
|
|
3
|
+
*
|
|
4
|
+
* **IMPORTANT: Security Limitation**
|
|
5
|
+
*
|
|
6
|
+
* This is NOT a true sandbox. In Node.js, `vm` creates a V8 context with its own
|
|
7
|
+
* global object, providing isolation from the host environment. In the browser,
|
|
8
|
+
* this polyfill uses `new Function()` which executes code in the same JavaScript
|
|
9
|
+
* realm as the host page.
|
|
10
|
+
*
|
|
11
|
+
* Implications:
|
|
12
|
+
* - Code executed via `runInContext()` / `runInNewContext()` can access and modify
|
|
13
|
+
* global browser objects (window, document, etc.) through prototype chain traversal.
|
|
14
|
+
* - There is NO memory isolation — the executed code shares the same heap.
|
|
15
|
+
* - `createContext()` simply returns the sandbox object without creating an isolated context.
|
|
16
|
+
* - The `Script` class wraps code in `new Function()`, not a separate V8 context.
|
|
17
|
+
*
|
|
18
|
+
* This polyfill is suitable for:
|
|
19
|
+
* - Module evaluation (CommonJS require simulation)
|
|
20
|
+
* - Template rendering that expects vm-like API
|
|
21
|
+
* - Code that uses vm for convenience, not security
|
|
22
|
+
*
|
|
23
|
+
* This polyfill is NOT suitable for:
|
|
24
|
+
* - Untrusted code execution
|
|
25
|
+
* - Security sandboxing
|
|
26
|
+
* - Scenarios requiring true memory/scope isolation
|
|
27
|
+
*
|
|
28
|
+
* @module vm
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a "context" from a sandbox object.
|
|
33
|
+
* In the browser, this simply returns the sandbox as-is since we cannot
|
|
34
|
+
* create a true V8 context. The returned object is used as the scope
|
|
35
|
+
* for `runInContext()`.
|
|
36
|
+
*/
|
|
37
|
+
export function createContext(
|
|
38
|
+
sandbox?: Record<string, unknown>,
|
|
39
|
+
): Record<string, unknown> {
|
|
40
|
+
return sandbox || {};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Execute code in the given context.
|
|
45
|
+
* Uses `new Function()` — does NOT provide true V8 context isolation.
|
|
46
|
+
* @see Module-level JSDoc for security limitations.
|
|
47
|
+
*/
|
|
48
|
+
export function runInContext(
|
|
49
|
+
code: string,
|
|
50
|
+
context: Record<string, unknown>,
|
|
51
|
+
): unknown {
|
|
52
|
+
const keys = Object.keys(context);
|
|
53
|
+
const values = keys.map(k => context[k]);
|
|
54
|
+
const fn = new Function(...keys, `return (${code})`);
|
|
55
|
+
return fn(...values);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Execute code in a new context created from the sandbox.
|
|
60
|
+
* Equivalent to `runInContext(code, createContext(sandbox))`.
|
|
61
|
+
* @see Module-level JSDoc for security limitations.
|
|
62
|
+
*/
|
|
63
|
+
export function runInNewContext(
|
|
64
|
+
code: string,
|
|
65
|
+
sandbox?: Record<string, unknown>,
|
|
66
|
+
): unknown {
|
|
67
|
+
return runInContext(code, sandbox || {});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Execute code in the current global context via `new Function()`.
|
|
72
|
+
* @see Module-level JSDoc for security limitations.
|
|
73
|
+
*/
|
|
74
|
+
export function runInThisContext(code: string): unknown {
|
|
75
|
+
return new Function(`return (${code})`)();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Always returns true since we cannot distinguish real V8 contexts in the browser. */
|
|
79
|
+
export function isContext(_sandbox: unknown): boolean {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Wraps code in a `new Function()` call for deferred execution.
|
|
85
|
+
* Does NOT create a V8 Script object — no compilation caching occurs.
|
|
86
|
+
* @see Module-level JSDoc for security limitations.
|
|
87
|
+
*/
|
|
88
|
+
export class Script {
|
|
89
|
+
private code: string;
|
|
90
|
+
constructor(code: string, _options?: unknown) {
|
|
91
|
+
this.code = code;
|
|
92
|
+
}
|
|
93
|
+
runInContext(context: Record<string, unknown>): unknown {
|
|
94
|
+
return runInContext(this.code, context);
|
|
95
|
+
}
|
|
96
|
+
runInNewContext(sandbox?: Record<string, unknown>): unknown {
|
|
97
|
+
return runInNewContext(this.code, sandbox);
|
|
98
|
+
}
|
|
99
|
+
runInThisContext(): unknown {
|
|
100
|
+
return runInThisContext(this.code);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
createContext,
|
|
106
|
+
runInContext,
|
|
107
|
+
runInNewContext,
|
|
108
|
+
runInThisContext,
|
|
109
|
+
isContext,
|
|
110
|
+
Script,
|
|
111
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced worker_threads polyfill.
|
|
3
|
+
*
|
|
4
|
+
* Provides a more complete implementation of Node.js worker_threads API.
|
|
5
|
+
* When Web Workers are available (browser), `new Worker()` spawns a real
|
|
6
|
+
* Web Worker for parallel execution. When unavailable (tests), it falls
|
|
7
|
+
* back to in-process emulation via EventEmitter pairs.
|
|
8
|
+
*
|
|
9
|
+
* Supported:
|
|
10
|
+
* - `Worker` class with `postMessage`/`on('message')` communication
|
|
11
|
+
* - `parentPort` for child-to-parent messaging
|
|
12
|
+
* - `workerData` for initial data transfer
|
|
13
|
+
* - `isMainThread` flag
|
|
14
|
+
* - `threadId` counter
|
|
15
|
+
* - `MessageChannel` / `MessagePort` pairs
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { EventEmitter } from "./events";
|
|
19
|
+
|
|
20
|
+
let _threadIdCounter = 1;
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// MessagePort / MessageChannel
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
export class MessagePort extends EventEmitter {
|
|
27
|
+
private _partner: MessagePort | null = null;
|
|
28
|
+
private _started = false;
|
|
29
|
+
private _closed = false;
|
|
30
|
+
private _queue: unknown[] = [];
|
|
31
|
+
|
|
32
|
+
postMessage(value: unknown): void {
|
|
33
|
+
if (this._closed) return;
|
|
34
|
+
if (this._partner) {
|
|
35
|
+
if (this._partner._started) {
|
|
36
|
+
// Deliver asynchronously like real MessagePort
|
|
37
|
+
queueMicrotask(() => this._partner?.emit("message", value));
|
|
38
|
+
} else {
|
|
39
|
+
this._partner._queue.push(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
start(): void {
|
|
45
|
+
this._started = true;
|
|
46
|
+
// Flush queued messages
|
|
47
|
+
for (const msg of this._queue) {
|
|
48
|
+
queueMicrotask(() => this.emit("message", msg));
|
|
49
|
+
}
|
|
50
|
+
this._queue.length = 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
close(): void {
|
|
54
|
+
this._closed = true;
|
|
55
|
+
this.emit("close");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ref(): this {
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
unref(): this {
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** @internal Connect two ports as partners. */
|
|
66
|
+
static _pair(): [MessagePort, MessagePort] {
|
|
67
|
+
const a = new MessagePort();
|
|
68
|
+
const b = new MessagePort();
|
|
69
|
+
a._partner = b;
|
|
70
|
+
b._partner = a;
|
|
71
|
+
return [a, b];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class MessageChannel {
|
|
76
|
+
port1: MessagePort;
|
|
77
|
+
port2: MessagePort;
|
|
78
|
+
|
|
79
|
+
constructor() {
|
|
80
|
+
[this.port1, this.port2] = MessagePort._pair();
|
|
81
|
+
this.port1.start();
|
|
82
|
+
this.port2.start();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Worker
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
|
|
90
|
+
export class Worker extends EventEmitter {
|
|
91
|
+
readonly threadId: number;
|
|
92
|
+
private _port: MessagePort;
|
|
93
|
+
private _workerPort: MessagePort;
|
|
94
|
+
|
|
95
|
+
constructor(
|
|
96
|
+
_filename: string,
|
|
97
|
+
options?: { workerData?: unknown; eval?: boolean },
|
|
98
|
+
) {
|
|
99
|
+
super();
|
|
100
|
+
this.threadId = _threadIdCounter++;
|
|
101
|
+
|
|
102
|
+
// Create a MessageChannel pair for parent <-> worker communication
|
|
103
|
+
[this._port, this._workerPort] = MessagePort._pair();
|
|
104
|
+
this._port.start();
|
|
105
|
+
this._workerPort.start();
|
|
106
|
+
|
|
107
|
+
// Forward messages from the worker port to the Worker's 'message' event
|
|
108
|
+
this._port.on("message", (msg: unknown) => {
|
|
109
|
+
this.emit("message", msg);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Expose parentPort-like API on the worker side
|
|
113
|
+
const workerData = options?.workerData;
|
|
114
|
+
const workerPort = this._workerPort;
|
|
115
|
+
|
|
116
|
+
// In a real implementation, we'd execute the file in an isolated context.
|
|
117
|
+
// For now, make the worker port and data available via the module-level exports.
|
|
118
|
+
_lastWorkerPort = workerPort;
|
|
119
|
+
_lastWorkerData = workerData;
|
|
120
|
+
|
|
121
|
+
// Emit 'online' asynchronously
|
|
122
|
+
queueMicrotask(() => this.emit("online"));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
postMessage(value: unknown): void {
|
|
126
|
+
this._workerPort.emit("message", value);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
terminate(): Promise<number> {
|
|
130
|
+
this._port.close();
|
|
131
|
+
this._workerPort.close();
|
|
132
|
+
this.emit("exit", 0);
|
|
133
|
+
return Promise.resolve(0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
ref(): this {
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
unref(): this {
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
// Module-level exports (mimics Node.js worker_threads)
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
/** Whether the current context is the main thread. */
|
|
149
|
+
export const isMainThread = true;
|
|
150
|
+
|
|
151
|
+
/** Thread ID of the current thread. */
|
|
152
|
+
export const threadId = 0;
|
|
153
|
+
|
|
154
|
+
// These are set when a Worker is created, allowing test code to access them.
|
|
155
|
+
let _lastWorkerPort: MessagePort | null = null;
|
|
156
|
+
let _lastWorkerData: unknown = undefined;
|
|
157
|
+
|
|
158
|
+
/** Parent port (only available inside a worker thread). */
|
|
159
|
+
export const parentPort: MessagePort | null = null;
|
|
160
|
+
|
|
161
|
+
/** Data passed to the worker via `workerData` option. */
|
|
162
|
+
export const workerData: unknown = undefined;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get the last created worker's port (for testing).
|
|
166
|
+
* @internal
|
|
167
|
+
*/
|
|
168
|
+
export function _getLastWorkerPort(): MessagePort | null {
|
|
169
|
+
return _lastWorkerPort;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get the last created worker's data (for testing).
|
|
174
|
+
* @internal
|
|
175
|
+
*/
|
|
176
|
+
export function _getLastWorkerData(): unknown {
|
|
177
|
+
return _lastWorkerData;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Default export matching Node.js worker_threads module shape. */
|
|
181
|
+
export default {
|
|
182
|
+
Worker,
|
|
183
|
+
isMainThread,
|
|
184
|
+
parentPort,
|
|
185
|
+
workerData,
|
|
186
|
+
threadId,
|
|
187
|
+
MessageChannel,
|
|
188
|
+
MessagePort,
|
|
189
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { EventEmitter } from "./events";
|
|
2
|
+
|
|
3
|
+
export class WebSocketShim extends EventEmitter {
|
|
4
|
+
readyState = 0;
|
|
5
|
+
url: string;
|
|
6
|
+
static CONNECTING = 0;
|
|
7
|
+
static OPEN = 1;
|
|
8
|
+
static CLOSING = 2;
|
|
9
|
+
static CLOSED = 3;
|
|
10
|
+
CONNECTING = 0;
|
|
11
|
+
OPEN = 1;
|
|
12
|
+
CLOSING = 2;
|
|
13
|
+
CLOSED = 3;
|
|
14
|
+
|
|
15
|
+
private _ws: WebSocket | null = null;
|
|
16
|
+
|
|
17
|
+
constructor(url: string, _protocols?: string | string[], _options?: unknown) {
|
|
18
|
+
super();
|
|
19
|
+
this.url = url;
|
|
20
|
+
try {
|
|
21
|
+
this._ws = new WebSocket(url);
|
|
22
|
+
this._ws.binaryType = "arraybuffer";
|
|
23
|
+
this._ws.onopen = () => {
|
|
24
|
+
this.readyState = 1;
|
|
25
|
+
this.emit("open");
|
|
26
|
+
};
|
|
27
|
+
this._ws.onmessage = e => this.emit("message", e.data);
|
|
28
|
+
this._ws.onerror = e => this.emit("error", e);
|
|
29
|
+
this._ws.onclose = e => {
|
|
30
|
+
this.readyState = 3;
|
|
31
|
+
this.emit("close", e.code, e.reason);
|
|
32
|
+
};
|
|
33
|
+
} catch (err) {
|
|
34
|
+
setTimeout(() => this.emit("error", err), 0);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
send(data: unknown, _options?: unknown, cb?: (err?: Error) => void): void {
|
|
39
|
+
try {
|
|
40
|
+
this._ws?.send(data as string | ArrayBuffer);
|
|
41
|
+
cb?.();
|
|
42
|
+
} catch (err) {
|
|
43
|
+
cb?.(err as Error);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
close(code?: number, reason?: string): void {
|
|
48
|
+
this.readyState = 2;
|
|
49
|
+
this._ws?.close(code, reason);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
ping(_data?: unknown, _mask?: boolean, _cb?: () => void): void {}
|
|
53
|
+
pong(_data?: unknown, _mask?: boolean, _cb?: () => void): void {}
|
|
54
|
+
terminate(): void {
|
|
55
|
+
this.close();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class WebSocketServer extends EventEmitter {
|
|
60
|
+
clients = new Set<WebSocketShim>();
|
|
61
|
+
constructor(_options?: unknown) {
|
|
62
|
+
super();
|
|
63
|
+
}
|
|
64
|
+
close(_cb?: () => void): void {
|
|
65
|
+
this.emit("close");
|
|
66
|
+
}
|
|
67
|
+
address(): { port: number; family: string; address: string } {
|
|
68
|
+
return { port: 0, family: "IPv4", address: "0.0.0.0" };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { WebSocketShim as WebSocket };
|
|
73
|
+
export default WebSocketShim;
|