@scelar/nodepod 1.0.2 → 1.0.3
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/__tests__/bench/integration.bench.d.ts +1 -0
- package/dist/__tests__/bench/memory-volume.bench.d.ts +1 -0
- package/dist/__tests__/bench/polyfills.bench.d.ts +1 -0
- package/dist/__tests__/bench/script-engine.bench.d.ts +1 -0
- package/dist/__tests__/bench/shell.bench.d.ts +1 -0
- package/dist/__tests__/bench/syntax-transforms.bench.d.ts +1 -0
- package/dist/__tests__/bench/version-resolver.bench.d.ts +1 -0
- package/dist/__tests__/buffer.test.d.ts +1 -0
- package/dist/__tests__/byte-encoding.test.d.ts +1 -0
- package/dist/__tests__/digest.test.d.ts +1 -0
- package/dist/__tests__/events.test.d.ts +1 -0
- package/dist/__tests__/memory-volume.test.d.ts +1 -0
- package/dist/__tests__/path.test.d.ts +1 -0
- package/dist/__tests__/process.test.d.ts +1 -0
- package/dist/__tests__/script-engine.test.d.ts +1 -0
- package/dist/__tests__/shell-builtins.test.d.ts +1 -0
- package/dist/__tests__/shell-interpreter.test.d.ts +1 -0
- package/dist/__tests__/shell-parser.test.d.ts +1 -0
- package/dist/__tests__/stream.test.d.ts +1 -0
- package/dist/__tests__/syntax-transforms.test.d.ts +1 -0
- package/dist/__tests__/version-resolver.test.d.ts +1 -0
- package/dist/{child_process-Dopvyd-E.js → child_process-D6oDN2MX.js} +4 -4
- package/dist/{child_process-Dopvyd-E.js.map → child_process-D6oDN2MX.js.map} +1 -1
- package/dist/{child_process-B38qoN6R.cjs → child_process-hmVqFcF7.cjs} +5 -5
- package/dist/{child_process-B38qoN6R.cjs.map → child_process-hmVqFcF7.cjs.map} +1 -1
- package/dist/{index--Qr8LVpQ.js → index-Ale2oba_.js} +240 -136
- package/dist/index-Ale2oba_.js.map +1 -0
- package/dist/{index-cnitc68U.cjs → index-BO1i013L.cjs} +236 -191
- package/dist/index-BO1i013L.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/script-engine.d.ts +2 -0
- package/dist/syntax-transforms.d.ts +1 -0
- package/package.json +97 -95
- package/src/__tests__/bench/integration.bench.ts +117 -0
- package/src/__tests__/bench/memory-volume.bench.ts +115 -0
- package/src/__tests__/bench/polyfills.bench.ts +147 -0
- package/src/__tests__/bench/script-engine.bench.ts +104 -0
- package/src/__tests__/bench/shell.bench.ts +101 -0
- package/src/__tests__/bench/syntax-transforms.bench.ts +82 -0
- package/src/__tests__/bench/version-resolver.bench.ts +95 -0
- package/src/__tests__/buffer.test.ts +273 -0
- package/src/__tests__/byte-encoding.test.ts +98 -0
- package/src/__tests__/digest.test.ts +44 -0
- package/src/__tests__/events.test.ts +245 -0
- package/src/__tests__/memory-volume.test.ts +443 -0
- package/src/__tests__/path.test.ts +181 -0
- package/src/__tests__/process.test.ts +129 -0
- package/src/__tests__/script-engine.test.ts +229 -0
- package/src/__tests__/shell-builtins.test.ts +357 -0
- package/src/__tests__/shell-interpreter.test.ts +157 -0
- package/src/__tests__/shell-parser.test.ts +204 -0
- package/src/__tests__/stream.test.ts +142 -0
- package/src/__tests__/syntax-transforms.test.ts +158 -0
- package/src/__tests__/version-resolver.test.ts +184 -0
- package/src/constants/cdn-urls.ts +18 -18
- package/src/helpers/byte-encoding.ts +51 -39
- package/src/memory-volume.ts +962 -941
- package/src/module-transformer.ts +368 -368
- package/src/packages/installer.ts +396 -396
- package/src/polyfills/buffer.ts +633 -628
- package/src/polyfills/esbuild.ts +854 -854
- package/src/polyfills/events.ts +282 -276
- package/src/polyfills/process.ts +695 -690
- package/src/polyfills/readline.ts +692 -692
- package/src/polyfills/tty.ts +71 -71
- package/src/script-engine.ts +3396 -3375
- package/src/syntax-transforms.ts +543 -561
- package/dist/index--Qr8LVpQ.js.map +0 -1
- package/dist/index-cnitc68U.cjs.map +0 -1
package/dist/index.cjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p, I, q, s, t, v, w, P, x, y, z, A, S, C, F, G, H, J, K, O, Q, U, X, Z, _, $, $ as $2, a0, a1, a2, a3, a4, l, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, ao, ap, aq, ar } from "./index
|
|
1
|
+
import { p, I, q, s, t, v, w, P, x, y, z, A, S, C, F, G, H, J, K, O, Q, U, X, Z, _, $, $ as $2, a0, a1, a2, a3, a4, l, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, ao, ap, aq, ar } from "./index-Ale2oba_.js";
|
|
2
2
|
export {
|
|
3
3
|
p as DependencyInstaller,
|
|
4
4
|
I as IframeSandbox,
|
package/dist/script-engine.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface ModuleRecord {
|
|
|
9
9
|
loaded: boolean;
|
|
10
10
|
children: ModuleRecord[];
|
|
11
11
|
paths: string[];
|
|
12
|
+
parent: ModuleRecord | null;
|
|
12
13
|
}
|
|
13
14
|
export interface EngineOptions {
|
|
14
15
|
cwd?: string;
|
|
@@ -31,6 +32,7 @@ export interface ResolverFn {
|
|
|
31
32
|
cache: Record<string, ModuleRecord>;
|
|
32
33
|
extensions: Record<string, unknown>;
|
|
33
34
|
main: ModuleRecord | null;
|
|
35
|
+
_ownerRecord?: ModuleRecord;
|
|
34
36
|
}
|
|
35
37
|
export declare class ScriptEngine {
|
|
36
38
|
private vol;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function esmToCjs(code: string): string;
|
|
2
|
+
export declare function collectEsmCjsPatches(ast: any, code: string, patches: Array<[number, number, string]>): void;
|
|
2
3
|
export declare function hasTopLevelAwait(code: string): boolean;
|
|
3
4
|
export declare function stripTopLevelAwait(code: string, mode?: "topLevelOnly" | "full"): string;
|
package/package.json
CHANGED
|
@@ -1,95 +1,97 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@scelar/nodepod",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Browser-native Node.js runtime environment",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT WITH Commons-Clause",
|
|
7
|
-
"author": "R1ck404 (https://github.com/R1ck404)",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/ScelarOrg/Nodepod.git"
|
|
11
|
-
},
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/ScelarOrg/Nodepod/issues"
|
|
14
|
-
},
|
|
15
|
-
"homepage": "https://github.com/ScelarOrg/Nodepod#readme",
|
|
16
|
-
"keywords": [
|
|
17
|
-
"node",
|
|
18
|
-
"browser",
|
|
19
|
-
"runtime",
|
|
20
|
-
"sandbox",
|
|
21
|
-
"typescript",
|
|
22
|
-
"virtual-filesystem",
|
|
23
|
-
"polyfill",
|
|
24
|
-
"webcontainer",
|
|
25
|
-
"in-browser",
|
|
26
|
-
"nodejs"
|
|
27
|
-
],
|
|
28
|
-
"engines": {
|
|
29
|
-
"node": ">=20.0.0"
|
|
30
|
-
},
|
|
31
|
-
"main": "./dist/index.cjs",
|
|
32
|
-
"module": "./dist/index.mjs",
|
|
33
|
-
"types": "./dist/index.d.ts",
|
|
34
|
-
"exports": {
|
|
35
|
-
".": {
|
|
36
|
-
"import": {
|
|
37
|
-
"types": "./dist/index.d.ts",
|
|
38
|
-
"default": "./dist/index.mjs"
|
|
39
|
-
},
|
|
40
|
-
"require": {
|
|
41
|
-
"types": "./dist/index.d.ts",
|
|
42
|
-
"default": "./dist/index.cjs"
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
"files": [
|
|
47
|
-
"src",
|
|
48
|
-
"dist"
|
|
49
|
-
],
|
|
50
|
-
"sideEffects": false,
|
|
51
|
-
"scripts": {
|
|
52
|
-
"build:lib": "vite build --config vite.lib.config.js &&
|
|
53
|
-
"build:types": "tsc --project tsconfig.build.json",
|
|
54
|
-
"build:publish": "npm run build:lib && npm run build:types",
|
|
55
|
-
"type-check": "tsc --noEmit",
|
|
56
|
-
"test": "vitest run",
|
|
57
|
-
"test:watch": "vitest"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"@xterm/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"vite
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@scelar/nodepod",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Browser-native Node.js runtime environment",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT WITH Commons-Clause",
|
|
7
|
+
"author": "R1ck404 (https://github.com/R1ck404)",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/ScelarOrg/Nodepod.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ScelarOrg/Nodepod/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/ScelarOrg/Nodepod#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"node",
|
|
18
|
+
"browser",
|
|
19
|
+
"runtime",
|
|
20
|
+
"sandbox",
|
|
21
|
+
"typescript",
|
|
22
|
+
"virtual-filesystem",
|
|
23
|
+
"polyfill",
|
|
24
|
+
"webcontainer",
|
|
25
|
+
"in-browser",
|
|
26
|
+
"nodejs"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20.0.0"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.cjs",
|
|
32
|
+
"module": "./dist/index.mjs",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"default": "./dist/index.mjs"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"default": "./dist/index.cjs"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"src",
|
|
48
|
+
"dist"
|
|
49
|
+
],
|
|
50
|
+
"sideEffects": false,
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build:lib": "vite build --config vite.lib.config.js && node -e \"require('fs').copyFileSync('static/__sw__.js','dist/__sw__.js')\"",
|
|
53
|
+
"build:types": "tsc --project tsconfig.build.json",
|
|
54
|
+
"build:publish": "npm run build:lib && npm run build:types",
|
|
55
|
+
"type-check": "tsc --noEmit",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest",
|
|
58
|
+
"bench": "vitest bench",
|
|
59
|
+
"bench:run": "vitest bench --run"
|
|
60
|
+
},
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"acorn": "^8.15.0",
|
|
63
|
+
"acorn-jsx": "^5.3.2",
|
|
64
|
+
"brotli": "^1.3.3",
|
|
65
|
+
"brotli-wasm": "^3.0.1",
|
|
66
|
+
"comlink": "^4.4.2",
|
|
67
|
+
"pako": "^2.1.0",
|
|
68
|
+
"resolve.exports": "^2.0.3",
|
|
69
|
+
"zod": "^4.3.6"
|
|
70
|
+
},
|
|
71
|
+
"peerDependencies": {
|
|
72
|
+
"@xterm/xterm": "^6.0.0",
|
|
73
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
74
|
+
"@xterm/addon-webgl": "^0.19.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependenciesMeta": {
|
|
77
|
+
"@xterm/xterm": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"@xterm/addon-fit": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"@xterm/addon-webgl": {
|
|
84
|
+
"optional": true
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/node": "^25.0.10",
|
|
89
|
+
"@types/pako": "^2.0.4",
|
|
90
|
+
"esbuild": "^0.27.2",
|
|
91
|
+
"typescript": "^5.9.3",
|
|
92
|
+
"vite": "^5.4.0",
|
|
93
|
+
"vite-plugin-top-level-await": "^1.6.0",
|
|
94
|
+
"vite-plugin-wasm": "^3.5.0",
|
|
95
|
+
"vitest": "^4.0.18"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { describe, bench } from "vitest";
|
|
2
|
+
import { MemoryVolume } from "../../memory-volume";
|
|
3
|
+
import { ScriptEngine } from "../../script-engine";
|
|
4
|
+
|
|
5
|
+
describe("Integration - end to end", () => {
|
|
6
|
+
bench("volume + engine + write + execute", () => {
|
|
7
|
+
const vol = new MemoryVolume();
|
|
8
|
+
vol.mkdirSync("/app", { recursive: true });
|
|
9
|
+
vol.writeFileSync(
|
|
10
|
+
"/app/index.js",
|
|
11
|
+
`
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const result = path.join('/home', 'user', 'project');
|
|
14
|
+
module.exports = result;
|
|
15
|
+
`,
|
|
16
|
+
);
|
|
17
|
+
const engine = new ScriptEngine(vol, { cwd: "/app" });
|
|
18
|
+
engine.runFile("/app/index.js");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
bench("5-module project with require chain", () => {
|
|
22
|
+
const vol = new MemoryVolume();
|
|
23
|
+
vol.mkdirSync("/app/src", { recursive: true });
|
|
24
|
+
|
|
25
|
+
vol.writeFileSync(
|
|
26
|
+
"/app/src/config.js",
|
|
27
|
+
"module.exports = { port: 3000, host: 'localhost' };",
|
|
28
|
+
);
|
|
29
|
+
vol.writeFileSync(
|
|
30
|
+
"/app/src/utils.js",
|
|
31
|
+
`
|
|
32
|
+
const path = require('path');
|
|
33
|
+
module.exports = {
|
|
34
|
+
resolve: (...args) => path.resolve(...args),
|
|
35
|
+
join: (...args) => path.join(...args),
|
|
36
|
+
};
|
|
37
|
+
`,
|
|
38
|
+
);
|
|
39
|
+
vol.writeFileSync(
|
|
40
|
+
"/app/src/logger.js",
|
|
41
|
+
`
|
|
42
|
+
const util = require('util');
|
|
43
|
+
module.exports = {
|
|
44
|
+
info: (...args) => util.format(...args),
|
|
45
|
+
error: (...args) => util.format('ERROR:', ...args),
|
|
46
|
+
};
|
|
47
|
+
`,
|
|
48
|
+
);
|
|
49
|
+
vol.writeFileSync(
|
|
50
|
+
"/app/src/router.js",
|
|
51
|
+
`
|
|
52
|
+
const { EventEmitter } = require('events');
|
|
53
|
+
class Router extends EventEmitter {
|
|
54
|
+
constructor() { super(); this.routes = []; }
|
|
55
|
+
add(method, path, handler) { this.routes.push({ method, path, handler }); }
|
|
56
|
+
}
|
|
57
|
+
module.exports = Router;
|
|
58
|
+
`,
|
|
59
|
+
);
|
|
60
|
+
vol.writeFileSync(
|
|
61
|
+
"/app/src/index.js",
|
|
62
|
+
`
|
|
63
|
+
const config = require('./config');
|
|
64
|
+
const utils = require('./utils');
|
|
65
|
+
const logger = require('./logger');
|
|
66
|
+
const Router = require('./router');
|
|
67
|
+
|
|
68
|
+
const router = new Router();
|
|
69
|
+
router.add('GET', '/', () => 'hello');
|
|
70
|
+
module.exports = { config, utils, logger, router };
|
|
71
|
+
`,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
const engine = new ScriptEngine(vol, { cwd: "/app" });
|
|
75
|
+
engine.runFile("/app/src/index.js");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
bench("ESM project with import/export conversion", () => {
|
|
79
|
+
const vol = new MemoryVolume();
|
|
80
|
+
vol.mkdirSync("/esm", { recursive: true });
|
|
81
|
+
|
|
82
|
+
vol.writeFileSync(
|
|
83
|
+
"/esm/math.js",
|
|
84
|
+
`
|
|
85
|
+
export function add(a, b) { return a + b; }
|
|
86
|
+
export function multiply(a, b) { return a * b; }
|
|
87
|
+
export default { add, multiply };
|
|
88
|
+
`,
|
|
89
|
+
);
|
|
90
|
+
vol.writeFileSync(
|
|
91
|
+
"/esm/index.js",
|
|
92
|
+
`
|
|
93
|
+
import math, { add, multiply } from './math.js';
|
|
94
|
+
const result = add(multiply(3, 4), 5);
|
|
95
|
+
export default result;
|
|
96
|
+
`,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const engine = new ScriptEngine(vol, { cwd: "/esm" });
|
|
100
|
+
engine.runFile("/esm/index.js");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
bench("snapshot round-trip: 100 files + save + restore + verify", () => {
|
|
104
|
+
const vol = new MemoryVolume();
|
|
105
|
+
vol.mkdirSync("/proj/src", { recursive: true });
|
|
106
|
+
for (let i = 0; i < 100; i++) {
|
|
107
|
+
vol.writeFileSync(
|
|
108
|
+
`/proj/src/mod${i}.js`,
|
|
109
|
+
`module.exports = { id: ${i} };`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const snapshot = vol.toSnapshot();
|
|
114
|
+
const restored = MemoryVolume.fromSnapshot(snapshot);
|
|
115
|
+
restored.readFileSync("/proj/src/mod50.js", "utf8");
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, bench, beforeEach } from "vitest";
|
|
2
|
+
import { MemoryVolume } from "../../memory-volume";
|
|
3
|
+
|
|
4
|
+
function populatedVolume(fileCount: number, fileSize: number): MemoryVolume {
|
|
5
|
+
const vol = new MemoryVolume();
|
|
6
|
+
vol.mkdirSync("/project", { recursive: true });
|
|
7
|
+
const content = "x".repeat(fileSize);
|
|
8
|
+
for (let i = 0; i < fileCount; i++) {
|
|
9
|
+
vol.writeFileSync(`/project/file-${i}.txt`, content);
|
|
10
|
+
}
|
|
11
|
+
return vol;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("MemoryVolume - write", () => {
|
|
15
|
+
let vol: MemoryVolume;
|
|
16
|
+
beforeEach(() => { vol = new MemoryVolume(); });
|
|
17
|
+
|
|
18
|
+
bench("writeFileSync - 100 bytes", () => {
|
|
19
|
+
vol.writeFileSync("/test.txt", "a".repeat(100));
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
bench("writeFileSync - 10KB", () => {
|
|
23
|
+
vol.writeFileSync("/test.txt", "a".repeat(10_000));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
bench("writeFileSync - 1MB", () => {
|
|
27
|
+
vol.writeFileSync("/test.txt", "a".repeat(1_000_000));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
bench("writeFileSync - binary Uint8Array 10KB", () => {
|
|
31
|
+
vol.writeFileSync("/test.bin", new Uint8Array(10_000));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
bench("writeFileSync - deep path (6 levels)", () => {
|
|
35
|
+
vol.writeFileSync("/a/b/c/d/e/f/file.txt", "data");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("MemoryVolume - read", () => {
|
|
40
|
+
let vol: MemoryVolume;
|
|
41
|
+
beforeEach(() => { vol = populatedVolume(100, 1000); });
|
|
42
|
+
|
|
43
|
+
bench("readFileSync - utf8", () => {
|
|
44
|
+
vol.readFileSync("/project/file-50.txt", "utf8");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
bench("readFileSync - binary", () => {
|
|
48
|
+
vol.readFileSync("/project/file-50.txt");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
bench("existsSync - hit", () => {
|
|
52
|
+
vol.existsSync("/project/file-50.txt");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
bench("existsSync - miss", () => {
|
|
56
|
+
vol.existsSync("/project/nonexistent.txt");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
bench("statSync", () => {
|
|
60
|
+
vol.statSync("/project/file-50.txt");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("MemoryVolume - directories", () => {
|
|
65
|
+
let vol: MemoryVolume;
|
|
66
|
+
beforeEach(() => { vol = populatedVolume(200, 100); });
|
|
67
|
+
|
|
68
|
+
bench("readdirSync - 200 entries", () => {
|
|
69
|
+
vol.readdirSync("/project");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
bench("mkdirSync recursive - 5 levels", () => {
|
|
73
|
+
vol.mkdirSync("/new/a/b/c/d", { recursive: true });
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("MemoryVolume - snapshot", () => {
|
|
78
|
+
bench("toSnapshot - 100 files", () => {
|
|
79
|
+
const vol = populatedVolume(100, 500);
|
|
80
|
+
vol.toSnapshot();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
bench("fromSnapshot - 100 files", () => {
|
|
84
|
+
const vol = populatedVolume(100, 500);
|
|
85
|
+
const snap = vol.toSnapshot();
|
|
86
|
+
MemoryVolume.fromSnapshot(snap);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
bench("toSnapshot - 500 files", () => {
|
|
90
|
+
const vol = populatedVolume(500, 200);
|
|
91
|
+
vol.toSnapshot();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
bench("fromSnapshot - 500 files", () => {
|
|
95
|
+
const vol = populatedVolume(500, 200);
|
|
96
|
+
const snap = vol.toSnapshot();
|
|
97
|
+
MemoryVolume.fromSnapshot(snap);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe("MemoryVolume - mixed workload", () => {
|
|
102
|
+
bench("create 50 files + read all + delete all", () => {
|
|
103
|
+
const vol = new MemoryVolume();
|
|
104
|
+
vol.mkdirSync("/work", { recursive: true });
|
|
105
|
+
for (let i = 0; i < 50; i++) {
|
|
106
|
+
vol.writeFileSync(`/work/f${i}.js`, `const x = ${i};`);
|
|
107
|
+
}
|
|
108
|
+
for (let i = 0; i < 50; i++) {
|
|
109
|
+
vol.readFileSync(`/work/f${i}.js`, "utf8");
|
|
110
|
+
}
|
|
111
|
+
for (let i = 0; i < 50; i++) {
|
|
112
|
+
vol.unlinkSync(`/work/f${i}.js`);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { describe, bench } from "vitest";
|
|
2
|
+
import { EventEmitter } from "../../polyfills/events";
|
|
3
|
+
import { Buffer } from "../../polyfills/buffer";
|
|
4
|
+
import * as pathPolyfill from "../../polyfills/path";
|
|
5
|
+
import {
|
|
6
|
+
bytesToBase64,
|
|
7
|
+
base64ToBytes,
|
|
8
|
+
bytesToHex,
|
|
9
|
+
} from "../../helpers/byte-encoding";
|
|
10
|
+
import { quickDigest } from "../../helpers/digest";
|
|
11
|
+
|
|
12
|
+
describe("EventEmitter", () => {
|
|
13
|
+
bench("on + emit (1 listener, 100 emits)", () => {
|
|
14
|
+
const ee = new EventEmitter();
|
|
15
|
+
ee.on("data", () => {});
|
|
16
|
+
for (let i = 0; i < 100; i++) ee.emit("data", i);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
bench("on + emit (10 listeners, 100 emits)", () => {
|
|
20
|
+
const ee = new EventEmitter();
|
|
21
|
+
for (let i = 0; i < 10; i++) ee.on("data", () => {});
|
|
22
|
+
for (let i = 0; i < 100; i++) ee.emit("data", i);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
bench("once + emit (100 cycles)", () => {
|
|
26
|
+
const ee = new EventEmitter();
|
|
27
|
+
for (let i = 0; i < 100; i++) {
|
|
28
|
+
ee.once("event", () => {});
|
|
29
|
+
ee.emit("event");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
bench("removeListener (10 listeners)", () => {
|
|
34
|
+
const ee = new EventEmitter();
|
|
35
|
+
const handlers = Array.from({ length: 10 }, () => () => {});
|
|
36
|
+
handlers.forEach((h) => ee.on("data", h));
|
|
37
|
+
handlers.forEach((h) => ee.removeListener("data", h));
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("Buffer", () => {
|
|
42
|
+
bench("Buffer.from(string, 'utf8') - 1KB", () => {
|
|
43
|
+
Buffer.from("x".repeat(1024));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
bench("Buffer.from(string, 'base64') - 1KB", () => {
|
|
47
|
+
const b64 = bytesToBase64(new Uint8Array(768));
|
|
48
|
+
Buffer.from(b64, "base64");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
bench("Buffer.from(string, 'hex') - 1KB", () => {
|
|
52
|
+
const hex = bytesToHex(new Uint8Array(512));
|
|
53
|
+
Buffer.from(hex, "hex");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
bench("Buffer.alloc(4096)", () => {
|
|
57
|
+
Buffer.alloc(4096);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
bench("Buffer.concat (10 x 1KB)", () => {
|
|
61
|
+
const chunks = Array.from({ length: 10 }, () => Buffer.alloc(1024));
|
|
62
|
+
Buffer.concat(chunks);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
bench("Buffer.toString('utf8') - 4KB", () => {
|
|
66
|
+
const buf = Buffer.alloc(4096, 0x61);
|
|
67
|
+
buf.toString("utf8");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
bench("Buffer.toString('base64') - 4KB", () => {
|
|
71
|
+
const buf = Buffer.alloc(4096, 0x61);
|
|
72
|
+
buf.toString("base64");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe("path polyfill", () => {
|
|
77
|
+
bench("join (3 segments)", () => {
|
|
78
|
+
pathPolyfill.join("/usr", "local", "bin");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
bench("resolve (relative)", () => {
|
|
82
|
+
pathPolyfill.resolve("src", "index.ts");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
bench("resolve (absolute)", () => {
|
|
86
|
+
pathPolyfill.resolve("/home/user", "project", "src");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
bench("dirname", () => {
|
|
90
|
+
pathPolyfill.dirname("/home/user/project/src/index.ts");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
bench("basename", () => {
|
|
94
|
+
pathPolyfill.basename("/home/user/project/src/index.ts");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
bench("extname", () => {
|
|
98
|
+
pathPolyfill.extname("/home/user/project/src/index.ts");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
bench("normalize (complex)", () => {
|
|
102
|
+
pathPolyfill.normalize("/home/user/../user/./project//src/./index.ts");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
bench("parse", () => {
|
|
106
|
+
pathPolyfill.parse("/home/user/project/src/index.ts");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("Byte encoding", () => {
|
|
111
|
+
const small = new Uint8Array(256);
|
|
112
|
+
const medium = new Uint8Array(10_000);
|
|
113
|
+
const large = new Uint8Array(100_000);
|
|
114
|
+
|
|
115
|
+
bench("bytesToBase64 - 256B", () => {
|
|
116
|
+
bytesToBase64(small);
|
|
117
|
+
});
|
|
118
|
+
bench("bytesToBase64 - 10KB", () => {
|
|
119
|
+
bytesToBase64(medium);
|
|
120
|
+
});
|
|
121
|
+
bench("bytesToBase64 - 100KB", () => {
|
|
122
|
+
bytesToBase64(large);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
bench("base64ToBytes - 10KB", () => {
|
|
126
|
+
const encoded = bytesToBase64(medium);
|
|
127
|
+
base64ToBytes(encoded);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
bench("bytesToHex - 10KB", () => {
|
|
131
|
+
bytesToHex(medium);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("quickDigest", () => {
|
|
136
|
+
bench("short string (50 chars)", () => {
|
|
137
|
+
quickDigest("a".repeat(50));
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
bench("medium string (5KB)", () => {
|
|
141
|
+
quickDigest("a".repeat(5_000));
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
bench("long string (50KB)", () => {
|
|
145
|
+
quickDigest("a".repeat(50_000));
|
|
146
|
+
});
|
|
147
|
+
});
|