fake-node 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
package/index.js CHANGED
@@ -1 +1,171 @@
1
- throw new ReferenceError('module is not defined');
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FakeNode = exports.Process = void 0;
40
+ const assert_1 = __importDefault(require("assert"));
41
+ const module_buffer = __importStar(require("buffer"));
42
+ // @ts-ignore
43
+ const module_path = __importStar(require("path"));
44
+ const module_punycode = __importStar(require("punycode"));
45
+ const module_querystring = __importStar(require("querystring"));
46
+ // @ts-ignore
47
+ const module_readline = __importStar(require("readline"));
48
+ // @ts-ignore
49
+ const module_stream = __importStar(require("stream"));
50
+ // @ts-ignore
51
+ const module_string_decoder = __importStar(require("string_decoder"));
52
+ const module_test = __importStar(require("test"));
53
+ // @ts-ignore
54
+ const module_url = __importStar(require("url"));
55
+ // @ts-ignore
56
+ const module_util = __importStar(require("util"));
57
+ const web_only_globals_json_1 = __importDefault(require("./web_only_globals.json"));
58
+ // todo: properly implement eval
59
+ const DEFAULT_GLOBALS = { Infinity, NaN, undefined, eval, isFinite, isNaN, parseFloat, parseInt, decodeURI, decodeURIComponent, encodeURI, encodeURIComponent, escape, unescape, Object, Function, Boolean, Symbol, Error, AggregateError, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, Number, BigInt, Math, Date, String, RegExp, Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, BigUint64Array, Float32Array, Float64Array, Map, Set, WeakMap, WeakSet, ArrayBuffer, SharedArrayBuffer, DataView, Atomics, JSON, WeakRef, FinalizationRegistry, Promise, Reflect, Proxy, Intl, AbortController, Blob, ByteLengthQueuingStrategy, atob, BroadcastChannel, btoa, clearInterval, clearTimeout, CloseEvent, CompressionStream, console, CountQueuingStrategy, Crypto, crypto, CryptoKey, CustomEvent, DecompressionStream, Event, EventSource, EventTarget, fetch, FormData, Headers, localStorage, MessageChannel, MessageEvent, MessagePort, Navigator, navigator, PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceObserver, PerformanceObserverEntryList, performance, queueMicrotask, ReadableByteStreamController, Response, Request, sessionStorage, setInterval, setTimeout, Storage, structuredClone, SubtleCrypto, DOMException, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStreamDefaultController, URL, URLSearchParams, WebAssembly, WebSocket, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter };
60
+ for (const name of web_only_globals_json_1.default) {
61
+ Object.defineProperty(DEFAULT_GLOBALS, name, { get: () => { throw new ReferenceError(`${name} is not defined`); } });
62
+ }
63
+ class Process {
64
+ fakeNode;
65
+ pid;
66
+ argv = [];
67
+ argv0 = '';
68
+ module;
69
+ code;
70
+ path;
71
+ constructor(fakeNode, { path = '', code, module }) {
72
+ this.fakeNode = fakeNode;
73
+ this.pid = fakeNode.nextPid;
74
+ fakeNode.nextPid++;
75
+ fakeNode.processes.set(this.pid, this);
76
+ this.code = code;
77
+ this.path = path;
78
+ this.module = module ?? false;
79
+ }
80
+ run() {
81
+ let code;
82
+ if (this.module) {
83
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode_process__.fakeNode.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
84
+ }
85
+ else {
86
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
87
+ }
88
+ let elt = document.createElement('script');
89
+ elt.textContent = code;
90
+ document.body.appendChild(elt);
91
+ }
92
+ }
93
+ exports.Process = Process;
94
+ class FakeNode {
95
+ static nextId = 0;
96
+ id;
97
+ globalName;
98
+ modules = new Map();
99
+ builtinModules = new Map([
100
+ ['assert', assert_1.default],
101
+ ['buffer', module_buffer],
102
+ ['path', module_path],
103
+ ['punycode', module_punycode],
104
+ ['querystring', module_querystring],
105
+ ['readline', module_readline],
106
+ ['stream', module_stream],
107
+ ['string_decoder', module_string_decoder],
108
+ ['test', module_test],
109
+ ['url', module_url],
110
+ ['util', module_util],
111
+ ]);
112
+ globals;
113
+ processes = new Map();
114
+ nextPid = 3;
115
+ window = window;
116
+ constructor() {
117
+ this.id = FakeNode.nextId;
118
+ FakeNode.nextId++;
119
+ this.globalName = '__fakeNode_' + this.id + '__';
120
+ // @ts-ignore
121
+ globalThis[this.globalName] = this;
122
+ this.globals = Object.create(DEFAULT_GLOBALS);
123
+ Object.assign(this.globals, { require: this.require, Buffer: module_buffer.Buffer });
124
+ }
125
+ require(module) {
126
+ if (module.startsWith('fake-node:')) {
127
+ module = module.slice('fake-node:'.length);
128
+ }
129
+ else if (module.startsWith('node:')) {
130
+ module = module.slice('node:'.length);
131
+ }
132
+ if (this.modules.has(module)) {
133
+ return this.modules.get(module);
134
+ }
135
+ else if (this.builtinModules.has(module)) {
136
+ return this.builtinModules.get(module);
137
+ }
138
+ else {
139
+ throw new Error(`cannot find module '${module}'`);
140
+ }
141
+ }
142
+ getGlobals(pid) {
143
+ const process = this.processes.get(pid);
144
+ if (process === undefined) {
145
+ throw new TypeError(`nonexistent PID in FakeNode.getGlobals call: ${pid}. If you do not know why this occured, it is probably a bug in fake-node. Please report it at https://github.com/speedydelete/fake-node/issues.`);
146
+ }
147
+ let scope = Object.create(this.globals);
148
+ scope.global = scope;
149
+ scope.globalThis = scope;
150
+ scope.__fakeNode_process__ = process;
151
+ if (process.path !== '') {
152
+ const pathParts = process.path.split('/');
153
+ scope.__dirname = pathParts.slice(0, -1).join('/');
154
+ scope.__filename = pathParts[pathParts.length - 1];
155
+ }
156
+ if (process.module !== false) {
157
+ scope.module = {
158
+ exports: {}
159
+ };
160
+ scope.exports = scope.module.exports;
161
+ }
162
+ return scope;
163
+ }
164
+ run(code) {
165
+ (new Process(this, { code, path: '/' })).run();
166
+ }
167
+ addModule(name, code) {
168
+ (new Process(this, { code, path: '/', module: name })).run();
169
+ }
170
+ }
171
+ exports.FakeNode = FakeNode;
package/index.ts CHANGED
@@ -1,80 +1,148 @@
1
1
 
2
- import globals from './globals';
3
-
4
- import * as module_assert from './modules/assert';
5
- import * as module_buffer from './modules/buffer';
6
- import * as module_fs from './modules/fs';
7
- import * as module_os from './modules/os';
8
- import * as module_path from './modules/path';
9
- import * as module_process from './modules/process';
10
- import * as module_querystring from './modules/querystring';
11
- import * as module_util from './modules/util';
12
-
13
- function setup(path?: string, argv: string[] = []): object {
14
- module_process._argv.argv = argv;
15
- let scope: {[key: string]: any} = {};
16
- Object.assign(scope, globals);
17
- let readonly: {[key: string]: any} = {};
18
- scope.global = scope;
19
- scope.globalThis = scope;
20
- globalThis.__fakeNode_oldWd = globalThis.__fakeNode_wd;
21
- if (path !== undefined) {
22
- const splitPath = path.split('/');
23
- readonly.__dirname = splitPath.slice(0, -1).join('/');
24
- readonly.__filename = splitPath[splitPath.length - 1];
25
- scope.__fakeNode_wd = readonly.__dirname;
26
- }
27
- Object.defineProperties(scope, Object.fromEntries(Object.entries(readonly).map(([name, value]) => [name, {value: value, writable: false}])));
28
- return scope;
29
- }
2
+ import module_assert from 'assert';
3
+ import * as module_buffer from 'buffer';
4
+ // @ts-ignore
5
+ import * as module_path from 'path';
6
+ import * as module_punycode from 'punycode';
7
+ import * as module_querystring from 'querystring';
8
+ // @ts-ignore
9
+ import * as module_readline from 'readline';
10
+ // @ts-ignore
11
+ import * as module_stream from 'stream';
12
+ // @ts-ignore
13
+ import * as module_string_decoder from 'string_decoder';
14
+ import * as module_test from 'test';
15
+ // @ts-ignore
16
+ import * as module_url from 'url';
17
+ // @ts-ignore
18
+ import * as module_util from 'util';
19
+ import WEB_ONLY_GLOBALS from './web_only_globals.json';
30
20
 
31
- globalThis.__fakeNode_setup = setup;
32
21
 
33
- function cleanup(): void {
34
- globalThis.__fakeNode_wd = globalThis.__fakeNode_oldWd;
22
+ // todo: properly implement eval
23
+ const DEFAULT_GLOBALS = {Infinity, NaN, undefined, eval, isFinite, isNaN, parseFloat, parseInt, decodeURI, decodeURIComponent, encodeURI, encodeURIComponent, escape, unescape, Object, Function, Boolean, Symbol, Error, AggregateError, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, Number, BigInt, Math, Date, String, RegExp, Array, Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, BigInt64Array, BigUint64Array, Float32Array, Float64Array, Map, Set, WeakMap, WeakSet, ArrayBuffer, SharedArrayBuffer, DataView, Atomics, JSON, WeakRef, FinalizationRegistry, Promise, Reflect, Proxy, Intl, AbortController, Blob, ByteLengthQueuingStrategy, atob, BroadcastChannel, btoa, clearInterval, clearTimeout, CloseEvent, CompressionStream, console, CountQueuingStrategy, Crypto, crypto, CryptoKey, CustomEvent, DecompressionStream, Event, EventSource, EventTarget, fetch, FormData, Headers, localStorage, MessageChannel, MessageEvent, MessagePort, Navigator, navigator, PerformanceEntry, PerformanceMark, PerformanceMeasure, PerformanceObserver, PerformanceObserverEntryList, performance, queueMicrotask, ReadableByteStreamController, Response, Request, sessionStorage, setInterval, setTimeout, Storage, structuredClone, SubtleCrypto, DOMException, TextDecoder, TextDecoderStream, TextEncoder, TextEncoderStream, TransformStreamDefaultController, URL, URLSearchParams, WebAssembly, WebSocket, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter};
24
+ for (const name of WEB_ONLY_GLOBALS) {
25
+ Object.defineProperty(DEFAULT_GLOBALS, name, {get: () => {throw new ReferenceError(`${name} is not defined`)}});
35
26
  }
36
27
 
37
- globalThis.__fakeNode_cleanup = cleanup;
38
28
 
39
- function run(code: string, argv: string[] = []): void {
40
- code = `with(window.__fakeNode_setup(undefined,${JSON.stringify(argv)})){(function(){${code}})();window.__fakeNode_cleanup();}`;
41
- let elt = document.createElement('script');
42
- elt.textContent = code;
43
- document.body.appendChild(elt);
44
- }
29
+ export class Process {
45
30
 
46
- function addModule(name: string, code: string): void {
47
- code = `with(window.__fakeNode_setup()){window.__fakeNode_modules.set('${name}',(function(){${code};return module.exports;})();window.__fakeNode_cleanup();}`;
48
- let elt = document.createElement('script');
49
- elt.textContent = code;
50
- document.body.appendChild(elt);
51
- }
31
+ fakeNode: FakeNode;
32
+ pid: number;
33
+ argv: string[] = [];
34
+ argv0: string = '';
35
+ module: false | string;
36
+ code: string;
37
+ path: string;
52
38
 
53
- function addBuiltinModule(name: string, data: any): void {
54
- globalThis.__fakeNode_builtinModules.set(name, data);
55
- }
39
+ constructor(fakeNode: FakeNode, {path = '', code, module}: {path?: string, code: string, module?: false | string}) {
40
+ this.fakeNode = fakeNode;
41
+ this.pid = fakeNode.nextPid;
42
+ fakeNode.nextPid++;
43
+ fakeNode.processes.set(this.pid, this);
44
+ this.code = code;
45
+ this.path = path;
46
+ this.module = module ?? false;
47
+ }
56
48
 
57
- function deleteModule(name: string): void {
58
- globalThis.__fakeNode_modules.delete(name);
59
- }
49
+ run(): void {
50
+ let code: string;
51
+ if (this.module) {
52
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){__fakeNode_process__.fakeNode.modules.set('${this.module},(function(){${this.code};return module.exports;})());}`;
53
+ } else {
54
+ code = `with(${this.fakeNode.globalName}.getGlobals(${this.pid})){(function(){${this.code}})();}`;
55
+ }
56
+ let elt = document.createElement('script');
57
+ elt.textContent = code;
58
+ document.body.appendChild(elt);
59
+ }
60
60
 
61
- function deleteBuiltinModule(name: string): void {
62
- globalThis.__fakeNode_builtinModules.delete(name);
63
61
  }
64
62
 
65
- addBuiltinModule('assert', module_assert);
66
- addBuiltinModule('buffer', module_buffer);
67
- addBuiltinModule('fs', module_fs);
68
- addBuiltinModule('os', module_os);
69
- addBuiltinModule('path', module_path);
70
- addBuiltinModule('process', module_process);
71
- addBuiltinModule('querystring', module_querystring);
72
- addBuiltinModule('util', module_util);
73
-
74
- export {
75
- run,
76
- addModule,
77
- addBuiltinModule,
78
- deleteModule,
79
- deleteBuiltinModule,
63
+
64
+ export class FakeNode {
65
+
66
+ static nextId: number = 0;
67
+ id: number;
68
+ globalName: string;
69
+
70
+ modules: Map<string, any> = new Map();
71
+ builtinModules: Map<string, any> = new Map<string, any>([
72
+ ['assert', module_assert],
73
+ ['buffer', module_buffer],
74
+ ['path', module_path],
75
+ ['punycode', module_punycode],
76
+ ['querystring', module_querystring],
77
+ ['readline', module_readline],
78
+ ['stream', module_stream],
79
+ ['string_decoder', module_string_decoder],
80
+ ['test', module_test],
81
+ ['url', module_url],
82
+ ['util', module_util],
83
+ ]);
84
+
85
+ globals: {[key: string]: any};
86
+
87
+ processes: Map<number, Process> = new Map();
88
+ nextPid: number = 3;
89
+
90
+ window: Window = window;
91
+
92
+ constructor() {
93
+ this.id = FakeNode.nextId;
94
+ FakeNode.nextId++;
95
+ this.globalName = '__fakeNode_' + this.id + '__';
96
+ // @ts-ignore
97
+ globalThis[this.globalName] = this;
98
+ this.globals = Object.create(DEFAULT_GLOBALS);
99
+ Object.assign(this.globals, {require: this.require, Buffer: module_buffer.Buffer});
100
+ }
101
+
102
+ require(module: string): any {
103
+ if (module.startsWith('fake-node:')) {
104
+ module = module.slice('fake-node:'.length);
105
+ } else if (module.startsWith('node:')) {
106
+ module = module.slice('node:'.length);
107
+ }
108
+ if (this.modules.has(module)) {
109
+ return this.modules.get(module);
110
+ } else if (this.builtinModules.has(module)) {
111
+ return this.builtinModules.get(module);
112
+ } else {
113
+ throw new Error(`cannot find module '${module}'`);
114
+ }
115
+ }
116
+
117
+ getGlobals(pid: number): object {
118
+ const process = this.processes.get(pid);
119
+ if (process === undefined) {
120
+ throw new TypeError(`nonexistent PID in FakeNode.getGlobals call: ${pid}. If you do not know why this occured, it is probably a bug in fake-node. Please report it at https://github.com/speedydelete/fake-node/issues.`);
121
+ }
122
+ let scope: {[key: string]: any} = Object.create(this.globals);
123
+ scope.global = scope;
124
+ scope.globalThis = scope;
125
+ scope.__fakeNode_process__ = process;
126
+ if (process.path !== '') {
127
+ const pathParts = process.path.split('/');
128
+ scope.__dirname = pathParts.slice(0, -1).join('/');
129
+ scope.__filename = pathParts[pathParts.length - 1];
130
+ }
131
+ if (process.module !== false) {
132
+ scope.module = {
133
+ exports: {}
134
+ };
135
+ scope.exports = scope.module.exports;
136
+ }
137
+ return scope;
138
+ }
139
+
140
+ run(code: string): void {
141
+ (new Process(this, {code, path: '/'})).run();
142
+ }
143
+
144
+ addModule(name: string, code: string): void {
145
+ (new Process(this, {code, path: '/', module: name})).run();
146
+ }
147
+
80
148
  }
package/package.json CHANGED
@@ -1,14 +1,39 @@
1
1
  {
2
2
  "name": "fake-node",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A fake version of Node that works in the browser",
5
5
  "license": "MIT",
6
6
  "author": "speedydelete",
7
- "type": "module",
7
+ "type": "commonjs",
8
8
  "main": "index.js",
9
9
  "homepage": "https://github.com/speedydelete/fake-node",
10
- "repository": "github:speedydelete/fake-node",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/speedydelete/fake-node.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/speedydelete/fake-node/issues"
16
+ },
11
17
  "scripts": {
12
- "test": "echo \"Error: no test specified\" && exit 1"
18
+ "test": "echo \"Error: no test specified\" && exit 1",
19
+ "build": "tsc"
20
+ },
21
+ "dependencies": {
22
+ "assert": "^2.1.0",
23
+ "buffer": "^6.0.3",
24
+ "path": "^0.12.7",
25
+ "punycode": "^2.3.1",
26
+ "querystring": "^0.2.1",
27
+ "readline": "^1.3.0",
28
+ "stream": "^0.0.3",
29
+ "string_decoder": "^1.3.0",
30
+ "test": "^3.3.0",
31
+ "url": "^0.11.4",
32
+ "util": "^0.12.5"
33
+ },
34
+ "devDependencies": {
35
+ "@types/assert": "^1.5.11",
36
+ "@types/punycode": "^2.1.4",
37
+ "typescript": "^5.7.3"
13
38
  }
14
39
  }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "resolveJsonModule": true,
5
+ "esModuleInterop": true,
6
+ "module": "NodeNext"
7
+ },
8
+ "files": ["index.ts"],
9
+ "exclude": ["node_modules"]
10
+ }