@serveryyswys/node.operit 0.0.0-stage → 0.1.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.
Files changed (148) hide show
  1. package/BUILTINS.json +383 -0
  2. package/DESIGN.md +513 -0
  3. package/LICENSE +201 -0
  4. package/NOTICE +17 -0
  5. package/README.md +311 -2
  6. package/dist/assert/strict.d.ts +2 -0
  7. package/dist/assert/strict.js +7 -0
  8. package/dist/assert.d.ts +3 -0
  9. package/dist/assert.js +483 -0
  10. package/dist/buffer.d.ts +60 -0
  11. package/dist/buffer.js +524 -0
  12. package/dist/child_process.d.ts +56 -0
  13. package/dist/child_process.js +371 -0
  14. package/dist/console.d.ts +60 -0
  15. package/dist/console.js +193 -0
  16. package/dist/constants.d.ts +2 -0
  17. package/dist/constants.js +19 -0
  18. package/dist/crypto.d.ts +76 -0
  19. package/dist/crypto.js +312 -0
  20. package/dist/diagnostics_channel.d.ts +36 -0
  21. package/dist/diagnostics_channel.js +76 -0
  22. package/dist/dns/promises.d.ts +34 -0
  23. package/dist/dns/promises.js +190 -0
  24. package/dist/dns.d.ts +88 -0
  25. package/dist/dns.js +259 -0
  26. package/dist/events.d.ts +40 -0
  27. package/dist/events.js +237 -0
  28. package/dist/fs/promises.d.ts +160 -0
  29. package/dist/fs/promises.js +130 -0
  30. package/dist/fs.d.ts +221 -0
  31. package/dist/fs.js +944 -0
  32. package/dist/http.d.ts +92 -0
  33. package/dist/http.js +319 -0
  34. package/dist/https.d.ts +296 -0
  35. package/dist/https.js +50 -0
  36. package/dist/index.d.ts +2821 -0
  37. package/dist/index.js +93 -0
  38. package/dist/lib/bridge.d.ts +60 -0
  39. package/dist/lib/bridge.js +207 -0
  40. package/dist/lib/bytes.d.ts +20 -0
  41. package/dist/lib/bytes.js +239 -0
  42. package/dist/lib/child-process-types.d.ts +45 -0
  43. package/dist/lib/child-process-types.js +2 -0
  44. package/dist/lib/console-types.d.ts +12 -0
  45. package/dist/lib/console-types.js +2 -0
  46. package/dist/lib/cwd.d.ts +2 -0
  47. package/dist/lib/cwd.js +32 -0
  48. package/dist/lib/deep-equal.d.ts +3 -0
  49. package/dist/lib/deep-equal.js +223 -0
  50. package/dist/lib/deflate.d.ts +2 -0
  51. package/dist/lib/deflate.js +234 -0
  52. package/dist/lib/diagnostics-channel-types.d.ts +7 -0
  53. package/dist/lib/diagnostics-channel-types.js +2 -0
  54. package/dist/lib/dns-driver.d.ts +14 -0
  55. package/dist/lib/dns-driver.js +85 -0
  56. package/dist/lib/dns-types.d.ts +22 -0
  57. package/dist/lib/dns-types.js +2 -0
  58. package/dist/lib/errors.d.ts +48 -0
  59. package/dist/lib/errors.js +424 -0
  60. package/dist/lib/fs-driver.d.ts +70 -0
  61. package/dist/lib/fs-driver.js +364 -0
  62. package/dist/lib/fs-env.d.ts +30 -0
  63. package/dist/lib/fs-env.js +157 -0
  64. package/dist/lib/fs-types.d.ts +19 -0
  65. package/dist/lib/fs-types.js +2 -0
  66. package/dist/lib/hashes.d.ts +27 -0
  67. package/dist/lib/hashes.js +432 -0
  68. package/dist/lib/http-driver.d.ts +30 -0
  69. package/dist/lib/http-driver.js +72 -0
  70. package/dist/lib/http-types.d.ts +18 -0
  71. package/dist/lib/http-types.js +2 -0
  72. package/dist/lib/inflate.d.ts +6 -0
  73. package/dist/lib/inflate.js +284 -0
  74. package/dist/lib/path-types.d.ts +37 -0
  75. package/dist/lib/path-types.js +2 -0
  76. package/dist/lib/paths.d.ts +8 -0
  77. package/dist/lib/paths.js +106 -0
  78. package/dist/lib/perf-hooks-types.d.ts +18 -0
  79. package/dist/lib/perf-hooks-types.js +2 -0
  80. package/dist/lib/process-driver.d.ts +31 -0
  81. package/dist/lib/process-driver.js +102 -0
  82. package/dist/lib/punycode.d.ts +8 -0
  83. package/dist/lib/punycode.js +179 -0
  84. package/dist/lib/stream-consumers-types.d.ts +4 -0
  85. package/dist/lib/stream-consumers-types.js +2 -0
  86. package/dist/lib/stream-types.d.ts +29 -0
  87. package/dist/lib/stream-types.js +2 -0
  88. package/dist/lib/timers-types.d.ts +18 -0
  89. package/dist/lib/timers-types.js +2 -0
  90. package/dist/lib/url-search-params.d.ts +26 -0
  91. package/dist/lib/url-search-params.js +281 -0
  92. package/dist/lib/url-types.d.ts +44 -0
  93. package/dist/lib/url-types.js +2 -0
  94. package/dist/lib/url-whatwg.d.ts +78 -0
  95. package/dist/lib/url-whatwg.js +857 -0
  96. package/dist/lib/util-types.d.ts +13 -0
  97. package/dist/lib/util-types.js +2 -0
  98. package/dist/lib/v8-types.d.ts +30 -0
  99. package/dist/lib/v8-types.js +2 -0
  100. package/dist/lib/zlib-types.d.ts +12 -0
  101. package/dist/lib/zlib-types.js +2 -0
  102. package/dist/module.d.ts +8 -0
  103. package/dist/module.js +102 -0
  104. package/dist/os.d.ts +80 -0
  105. package/dist/os.js +247 -0
  106. package/dist/path/posix.d.ts +2 -0
  107. package/dist/path/posix.js +7 -0
  108. package/dist/path/win32.d.ts +2 -0
  109. package/dist/path/win32.js +10 -0
  110. package/dist/path.d.ts +3 -0
  111. package/dist/path.js +1222 -0
  112. package/dist/perf_hooks.d.ts +36 -0
  113. package/dist/perf_hooks.js +144 -0
  114. package/dist/process.d.ts +69 -0
  115. package/dist/process.js +230 -0
  116. package/dist/punycode.d.ts +22 -0
  117. package/dist/punycode.js +53 -0
  118. package/dist/querystring.d.ts +15 -0
  119. package/dist/querystring.js +209 -0
  120. package/dist/stream/consumers.d.ts +24 -0
  121. package/dist/stream/consumers.js +75 -0
  122. package/dist/stream/promises.d.ts +5 -0
  123. package/dist/stream/promises.js +10 -0
  124. package/dist/stream.d.ts +84 -0
  125. package/dist/stream.js +875 -0
  126. package/dist/string_decoder.d.ts +15 -0
  127. package/dist/string_decoder.js +237 -0
  128. package/dist/sys.d.ts +8 -0
  129. package/dist/sys.js +9 -0
  130. package/dist/timers/promises.d.ts +19 -0
  131. package/dist/timers/promises.js +74 -0
  132. package/dist/timers.d.ts +21 -0
  133. package/dist/timers.js +41 -0
  134. package/dist/tty.d.ts +9 -0
  135. package/dist/tty.js +25 -0
  136. package/dist/unsupported.d.ts +12 -0
  137. package/dist/unsupported.js +17 -0
  138. package/dist/url.d.ts +28 -0
  139. package/dist/url.js +486 -0
  140. package/dist/util/types.d.ts +16 -0
  141. package/dist/util/types.js +9 -0
  142. package/dist/util.d.ts +63 -0
  143. package/dist/util.js +527 -0
  144. package/dist/v8.d.ts +25 -0
  145. package/dist/v8.js +127 -0
  146. package/dist/zlib.d.ts +88 -0
  147. package/dist/zlib.js +371 -0
  148. package/package.json +31 -4
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 serveryyswys
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,17 @@
1
+ @serveryyswys/node.operit
2
+ Copyright 2026 serveryyswys
3
+
4
+ This product includes software developed by serveryyswys
5
+ (https://www.serveryyswys.top/).
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ http://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
package/README.md CHANGED
@@ -1,3 +1,312 @@
1
- # Temporary Holding Version
1
+ # node.operit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 为 **Operit 的 CommonJS 运行时**补齐 Node 核心能力。
4
+
5
+ ## 为什么需要它
6
+
7
+ Operit 的沙箱脚本跑在 QuickJS 上,内建了 CommonJS,但:
8
+
9
+ - **裸模块只有三个**:`require('lodash')` → 运行时的迷你 `_`,`require('uuid')` → 手写 v4,`require('axios')` → `http_request` 的薄封装
10
+ - **其余裸模块静默返回 `{}`**,不报错
11
+ - **`require` 只读 toolpkg 归档内的资源**,且只按发起模块的目录解析相对路径
12
+ - **没有 `node_modules` 上溯,没有 `package.json` 的 `main` / `exports` 解析**
13
+
14
+ node.operit 补的是"运行时故意没有实现"的那部分:真实的 `fs`、`path`、`os`……而"把裸名解析成路径"由 **OperitPackageManager(OPM,自建 npm)在打包期重写**完成。
15
+
16
+ ## 谁负责什么
17
+
18
+ | | OperitPackageManager(构建期) | node.operit(运行期) |
19
+ |---|---|---|
20
+ | 裸名 → 路径 | ✅ 读 `BUILTINS.json` 生成重写规则 | 只提供被映射到的实现 |
21
+ | `main` / `exports`、扩展名、`node_modules` 上溯 | ✅ | ❌ |
22
+ | Node 语义(错误码、Buffer、fs 行为) | ❌ | ✅ |
23
+
24
+ ## 开发者规范(硬约束)
25
+
26
+ 运行时读模块只走 toolpkg 归档,所以:
27
+
28
+ > **"把裸名重写成相对路径" 和 "把 `node_modules` 打进 toolpkg" 是同一件事的两半,缺一半就是废包。**
29
+
30
+ 1. `node_modules` 放**项目顶层**,不要放进 `dist/`
31
+ 2. 进 toolpkg 的必须是**运行期可达闭包**:`dependencies` 全量 + 嵌套 `node_modules`;`devDependencies` / `src/` / `tsconfig.json` / 测试一律不进
32
+ 3. `package.json` 与 `package-lock.json` 一并打包
33
+ 4. **node.operit 不可被裁剪**
34
+ 5. 重写输出路径**一律显式带 `.js`**(见下)
35
+ 6. 只要依赖碰到 Node 核心模块,就必须引入 node.operit
36
+
37
+ 两种失败模式完全不同,构建期要分别校验:
38
+
39
+ | 漏了什么 | 表现 |
40
+ |---|---|
41
+ | 裸名漏重写 | **静默返回 `{}`**,在别处炸 |
42
+ | 路径漏打包 | **显式抛** `Cannot resolve module "..." from "..."` |
43
+
44
+ ## 为什么重写必须带显式扩展名
45
+
46
+ Operit 的 `buildCandidatePaths` 第一句是 `if (/\.[a-z0-9]+$/i.test(normalized)) return [normalized];`。
47
+ 包名里的 `.operit` 正好命中这个正则,因此:
48
+
49
+ - ❌ `require('.../node_modules/@serveryyswys/node.operit')` → 只试这一个候选,解析失败
50
+ - ✅ `require('.../node_modules/@serveryyswys/node.operit/dist/index.js')`
51
+ - ✅ `require('.../node_modules/@serveryyswys/node.operit/dist/path.js')`
52
+
53
+ ## 契约
54
+
55
+ 完整映射表见 [`BUILTINS.json`](BUILTINS.json)。重写目标由 `distDir` + `subpath` 组成,与 Node 内置名一一对应:
56
+
57
+ | Node 内置 | 重写目标 |
58
+ |---|---|
59
+ | `require('path')` | `<rel>/node_modules/@serveryyswys/node.operit/dist/path.js` |
60
+ | `require('path/posix')` | `<rel>/node_modules/@serveryyswys/node.operit/dist/path/posix.js` |
61
+ | `require('fs/promises')` | `<rel>/node_modules/@serveryyswys/node.operit/dist/fs/promises.js` |
62
+
63
+ `status` 的含义:`ready` 可映射;`partial` 可映射但需读 `note`;`planned` 与 `unsupported` **必须由重写器报构建错误**,不得静默映射。
64
+
65
+ ## 目录
66
+
67
+ ```
68
+ node.operit/
69
+ src/ TypeScript 源码
70
+ index.ts 聚合入口(糖)
71
+ path.ts path 本体
72
+ path/posix.ts path/posix 子路径入口
73
+ path/win32.ts path/win32 子路径入口
74
+ buffer.ts Buffer
75
+ fs.ts fs 同步面(Node 语义)
76
+ fs/promises.ts fs/promises 子路径入口
77
+ events.ts EventEmitter
78
+ querystring.ts querystring
79
+ string_decoder.ts StringDecoder
80
+ util.ts util(format / inspect / promisify / TextEncoder 等)
81
+ os.ts os
82
+ process.ts process(require('process') 返回的进程对象)
83
+ crypto.ts crypto(哈希/HMAC/PBKDF2/随机数)
84
+ zlib.ts zlib(deflate/inflate/gzip/gunzip + 流式接口)
85
+ stream.ts stream(Readable/Writable/Duplex/Transform/PassThrough + pipeline/finished)
86
+ stream/promises.ts stream/promises 子路径入口
87
+ child_process.ts exec / execFile / spawn(同步宿主)
88
+ url.ts url(WHATWG URL + URLSearchParams + 旧版 parse/format/resolve)
89
+ timers.ts timers(含 setImmediate、promisify(setTimeout))
90
+ timers/promises.ts timers/promises
91
+ perf_hooks.ts perf_hooks(performance + constants)
92
+ constants.ts constants(fs/os/zlib/crypto 常量合并)
93
+ module.ts module(builtinModules / isBuiltin)
94
+ tty.ts tty(isatty 恒 false)
95
+ http.ts http(仅客户端,建在 toolCall('http_request') 之上)
96
+ https.ts https(同 http,缺省协议为 https:)
97
+ dns.ts dns(lookup 一族;resolve 一族显式拒绝)
98
+ dns/promises.ts dns/promises 子路径入口
99
+ assert.ts assert(含 AssertionError)
100
+ assert/strict.ts assert/strict 子路径入口
101
+ unsupported.ts 运行时显式拒绝
102
+ lib/
103
+ bridge.ts 唯一接触 Java bridge 的地方
104
+ errors.ts Node 错误码 + Java 异常映射
105
+ bytes.ts 二进制通道的唯一开关 + UTF-8 编解码
106
+ paths.ts 运行时路径根
107
+ cwd.ts cwd 持有者(打破 path/fs 循环)
108
+ fs-env.ts fs 环境状态机
109
+ fs-driver.ts 文件系统原语 + Java 驱动
110
+ hashes.ts md5/sha1/sha256/sha512 + HMAC + PBKDF2(纯 JS)
111
+ inflate.ts DEFLATE 解压 + CRC-32 / Adler-32(纯 JS)
112
+ deflate.ts DEFLATE 压缩:定长 Huffman + LZ77(纯 JS)
113
+ stream-types.ts stream 的公开类型
114
+ zlib-types.ts zlib 的公开类型
115
+ fs-types.ts fs 流式接口的公开类型
116
+ deep-equal.ts 深比较(util.isDeepStrictEqual 与 assert 共用)
117
+ punycode.ts RFC 3492(url 的域名转换)
118
+ url-types.ts url 的公开类型
119
+ url-search-params.ts URLSearchParams(url 与 url-whatwg 共用)
120
+ url-whatwg.ts WHATWG URL(RFC 3986 状态机)
121
+ timers-types.ts timers 的公开类型
122
+ perf-hooks-types.ts perf_hooks 的公开类型
123
+ http-driver.ts http 的宿主驱动(toolCall('http_request'))
124
+ http-types.ts http 的公开类型
125
+ dns-driver.ts dns 的宿主驱动(InetAddress / getaddrinfo)
126
+ dns-types.ts dns 的公开类型
127
+ process-driver.ts child_process 的宿主驱动(ProcessBuilder)
128
+ child-process-types.ts child_process 的公开类型
129
+ path-types.ts path 的公开类型
130
+ host.d.ts Operit 全局面声明
131
+ dist/ tsc 产物(发布内容,git 忽略)
132
+ BUILTINS.json 契约表:重写器读这个
133
+ test/ 本地对拍(不进包)
134
+ tsconfig.json
135
+ ```
136
+
137
+ ## 构建与测试
138
+
139
+ ```bash
140
+ npm run build # tsc -p tsconfig.json -> dist/
141
+ npm test # node test/run-tests.js(先自行 build)
142
+ ```
143
+
144
+ `path` 的 posix 部分与 Node 的 `path.posix` **全量对拍、一字不差**;win32 部分做真实场景硬断言 + 全量分歧普查。
145
+
146
+ ## 关于 `process` / `Buffer` 全局(**实测出来的契约要求**)
147
+
148
+ Operit 的运行时**没有** `process`,也没有 `Buffer`。node.operit 提供的是
149
+ `require('process')` / `require('buffer')`。
150
+
151
+ **只在入口文件里 `var process = ...` 一次是不够的** —— 必须把它挂成**全局**:
152
+
153
+ ```js
154
+ globalThis.process = require('<rel>/node_modules/@serveryyswys/node.operit/dist/process.js');
155
+ globalThis.Buffer = require('<rel>/node_modules/@serveryyswys/node.operit/dist/buffer.js').Buffer;
156
+ ```
157
+
158
+ 原因是真实包会做**特性探测**,而探测的是全局:
159
+
160
+ - `supports-color` 顶层就是 `const {env} = process`,没有全局时 **require 阶段直接抛**
161
+ `process is not defined`(`debug` / `chalk` 都依赖它);
162
+ - `debug` 用 `typeof process === 'undefined'` 在 browser / node 两套实现间切换,
163
+ 没有全局就会走 browser 分支(用 localStorage 而不是环境变量)。
164
+
165
+ 这是端到端验证撞出来的,并且做了**对照实验**(`integration/tools/run.js` 的"对照实验"一节:
166
+ 同一份打包产物,开 / 关 `injectProcess` 各跑一遍):
167
+
168
+ | | 不注入 | 注入 | Node |
169
+ | --- | --- | --- | --- |
170
+ | `supports-color` | require 即抛 | `["stderr","stdout","supportsColor"]`、`stdout=false` | 同左 ✓ |
171
+ | `debug` | 走 browser 分支 | 走 node 分支 | node 分支 |
172
+
173
+ 这条已经作为契约规则写进 `BUILTINS.json` 的 `packing` 段。
174
+
175
+ ## 端到端验证(真实 npm 包)
176
+
177
+ `npm run test:integration` —— 见 [integration/](integration/)。这一步回答的是
178
+ "真装一个 npm 包,按契约打包后能不能跑",而不只是"API 对不对拍"。
179
+
180
+ 它做四件事:
181
+
182
+ 1. `npm install` 真实包(`ms`、`iconv-lite`、`safer-buffer`、`semver`、`marked`、`diff`、`dayjs`、`debug`、`supports-color`);
183
+ 2. 按 `BUILTINS.json` 的 `packing` 规则做裸名重写(Node 内建 → `node.operit` 子路径,
184
+ npm 包 → 包入口,`.json` → 包装模块);
185
+ 3. 用**忠实复刻** `JsExecutionScriptBuilder.kt` 的运行时模拟器加载
186
+ (没有 node_modules 查找、未知裸名静默返回 `{}`、加载期没有 `process`/`Buffer` 全局);
187
+ 4. 同一份产物再用 Node 原生加载器跑一遍,**纯函数型包的 29 个结果字段必须逐字段一致**
188
+ (`ms` / `iconv-lite` / `semver` / `marked` / `diff` / `dayjs`);
189
+ 5. 会做 `typeof process` 特性探测的包(`debug` / `supports-color`)单独一组,
190
+ 只报不判 —— 它们在两边的代码路径本来就不同,而那正是上面那条契约要求的由来。
191
+
192
+ 第 4 步是关键:它把"模拟器里能跑"和"代码本身是对的"分开,否则一个坏掉的模拟器也能"跑通"。
193
+
194
+ ### 这一步抓到的真实缺陷
195
+
196
+ - **`Buffer` 的静态成员必须是可枚举的**。Node 的 `Buffer.from` 等是赋值出来的、可枚举;
197
+ 而 `class` 的 `static` 方法不可枚举。`safer-buffer`(iconv-lite 的依赖)正是用
198
+ `for (key in Buffer)` 做能力探测 —— 不可枚举时它复制出空对象,`Buffer.concat` 随即消失。
199
+ **纯 API 对拍看不出这个差异**,只有跑真实包才暴露。
200
+ > **更正**:本文档早先写着"`.json` 的 require 会被静默吃掉"。**那是错的** ——
201
+ > 它来自一次读漏:我把运行时模拟器写成了"JSON 当 JS 执行",于是导出恒为空对象,
202
+ > 再据此写进文档,形成自我印证。当前 `Operit-src` 的 `executeModule`(`JsExecutionScriptBuilder.kt:1231`)
203
+ > 有显式的 `.json` 分支,走 `JSON.parse`。模拟器已按此修正,并有直接验证:
204
+ > `require('./data.json')` 得到 `[1,2,3]`、嵌套对象取值也正确。
205
+ >
206
+ > 重写器**仍然可选地**生成 `.json` 包装模块,只为兼容早于该分支的 Operit 构建;
207
+ > 在当前源码上它不是必需的。`integration` 默认开着,这样产物与构建版本无关。
208
+
209
+ ## 运行时的模块解析语义(据源码 + 真机实测)
210
+
211
+ 这一节是给**打包方(OperitPackageManager / OPM)**看的。搞错任何一条,产物就会"装好了但 require 不到"。
212
+
213
+ | 事实 | 依据 |
214
+ | --- | --- |
215
+ | `require` **只从 toolpkg 归档里读模块**:`NativeInterface.readToolPkgTextResource(toolPkgId, path)`,**完全不碰文件系统** | `readToolPkgModule` :675 |
216
+ | 所以把 `node_modules` 铺在 `/sdcard` 上,运行期**永远 require 不到** —— 这与"有没有重写裸名"是两件事 | 同上;真机实测复现 |
217
+ | **必须是正规 toolpkg**(有 `toolPkgId`、入口已注册为 screen)。**单文件 `.js` 沙盒包不行**:`screenPath` 为空、也没有归档资源 → 所有路径型 require 全部失败 | `screenPath` :663;真机实测 |
218
+ | 裸名(不以 `./` 或 `/` 开头)→ 除 `lodash`/`uuid`/`axios` 外**静默返回 `{}`**,不抛错 | :1288 |
219
+ | 路径型请求解析不到 → 抛 `Cannot resolve module "x" from "<root>"` | :1301 |
220
+ | **入口脚本**的相对 require 以 `dirname(screenPath)` 为基准(`screenPath` = `moduleSpec.screen` = 入口脚本路径) | :1316 / :663 |
221
+ | **嵌套模块**的相对 require 以**自身路径**为基准 —— 标准 CommonJS | :1242 |
222
+ | `normalizePath` 丢掉开头的 `/`,且**越界的 `..` 直接丢弃**(逃不出根) | :209 |
223
+ | 名字命中 `/\.[a-z0-9]+$/i` 就**只有一个候选**,不补 `.js` —— 所以重写目标必须显式带扩展名 | :254 |
224
+ | `.json` 走 `JSON.parse`(当前源码) | :1231 |
225
+
226
+ **结论**:重写的目标路径要**相对入口脚本所在目录**(对嵌套模块则是相对自身,两者在正常的
227
+ "入口在包根"布局下一致),并且 `node_modules` 必须**进归档**,不能只铺在外部存储上。
228
+
229
+ ## 真机自检
230
+
231
+ `tools/device-check.js` 是一个**在 Operit 里跑的**自检脚本(不是桌面工具)。
232
+ 库里所有 Java 侧的行为在桌面上都无法验证,只能靠推断;这个脚本把"未验证"变成
233
+ "跑一次就知道":它逐项探测每一条宿主假设(bridge 信封形状、数组转换、
234
+ `File`/`RandomAccessFile`/`Files` 的语义、`ProcessBuilder`、`UUID`、
235
+ `InetAddress`、`toolCall('http_request')` 的返回形状、各个全局函数……),
236
+ 再跑一遍 node.operit 自身的端到端冒烟,最后打印 PASS/FAIL 报告。
237
+
238
+ 用法:在 Operit 里执行该脚本;若库不在默认位置,先设
239
+ `globalThis.ONJ_LIB_PATH = '<相对路径>/node_modules/@serveryyswys/node.operit/index.js'`。
240
+
241
+ `tools/device-check-dryrun.js` 是它的桌面试跑(用桩 NativeInterface 驱动),
242
+ 只验证**脚本本身**能跑完、能出报告 —— Java 行为仍然只能靠真机。
243
+
244
+ ### 一个实测出来的使用注意
245
+
246
+ `fs.env.use('config')` 要求**根已存在**;而插件的配置目录(`getPluginConfigDir('')`)
247
+ 不一定被 Operit 预先创建过。所以插件里应当先确认/创建该目录,再切到 `config` 环境 ——
248
+ `tools/device-check.js` 里就是这么做的,可以直接照抄。
249
+
250
+ ## 已知偏差
251
+
252
+ `path/win32` 被标为 **partial**。在 4000 条随机路径 + 固定语料的对拍中,与 Node `path.win32` 的总体分歧率约 **1.5%**,集中在两类边缘:
253
+
254
+ 1. 归一化含**歧义冒号**的相对路径(如 `'9:'`):Node 会补 `.` 前缀,本实现部分场景未补
255
+ 2. **UNC 根**的 `dirname` / `parse` 边界
256
+
257
+ 日常 Windows 路径形态(盘符、反斜杠、UNC、`..`、扩展名)经对拍一致。Operit 平台是 android/linux,该模块主要服务于解析 Windows 路径的三方库。
258
+
259
+ ## 状态
260
+
261
+ - `path`、`path/posix`:**ready**,posix 与 Node 全量对拍、一字不差
262
+ - `buffer`:**ready**,与 Node 的 Buffer 逐项对拍通过
263
+ - `events` / `querystring` / `string_decoder`:**ready**,行为序列与 Node 对拍一致
264
+ - `util`:**partial** —— `format` / `promisify` / `inherits` / `types` / `isDeepStrictEqual` /
265
+ `TextEncoder` / `TextDecoder` 已对拍;`inspect` 只对齐常用形态(Node 的 compact/breakLength 折行未照搬)
266
+ - `os` / `process`:**partial**,形状与语义对齐 Node,取值来自 Android;近似点见 `BUILTINS.json`
267
+ - `crypto`:**partial** —— 哈希/HMAC/PBKDF2/随机数与 Node 全量对拍通过;分组密码、签名、密钥对未实现(调用即抛 `ONJ_UNSUPPORTED`)
268
+ - `zlib`:**partial** —— 与 Node **双向**对拍通过(Node 压的我们解、我们压的 Node 解);
269
+ 压缩侧只有定长 Huffman,压缩率低于 zlib;流式接口基于 `stream.Transform` 但内部仍一次性处理;Brotli 未实现
270
+ - `stream` / `stream/promises`:**partial** —— 9 个场景与 Node 对拍一致;
271
+ 事件时序用 `queueMicrotask` 调度(同类但非逐拍相同);`objectMode` 的完整语义差异、
272
+ `cork` 合并优化、`compose` 未实现。
273
+ 注意 `stream.pipeline` 不给回调会按 Node 语义抛错,Promise 形式用 `stream/promises`
274
+ - `dns`:**partial** —— `lookup` 一族可用(基于 `java.net.InetAddress`);
275
+ **`resolve*` 与 `reverse` 显式抛 `ONJ_UNSUPPORTED`** —— 记录级查询要 JNDI 的 DNS provider,
276
+ 而 `com.sun.jndi.dns` 不在 Android 里,这是平台不成立不是尚未实现
277
+ - `http` / `https`:**partial** —— **只有客户端**,建在宿主的 `toolCall('http_request')` 之上
278
+ (不直接用 Java socket:那是走用户审批的工具,另起一套会绕过权限模型);
279
+ `createServer` 构造时显式抛 `ONJ_UNSUPPORTED`;请求体只支持文本;`abort()` 无法真正取消已发出的请求
280
+ - `timers` / `timers/promises` / `perf_hooks` / `constants` / `module` / `tty`:**partial** ——
281
+ 已对拍;`setImmediate` 落在 `setTimeout(…,0)` 上(同队列,Node 里它在 check 阶段);
282
+ `tty.isatty()` 恒 `false`;`module.createRequire` 显式拒绝;`constants` 给的是 **Linux/Android** 数值
283
+ - `url`:**partial** —— `URLSearchParams`、**WHATWG `URL`**、旧版 `parse`/`format`/`resolve`、
284
+ `pathToFileURL`/`fileURLToPath`(**POSIX 规则**)、`urlToHttpOptions`、
285
+ `domainToASCII`/`domainToUnicode` 均已对拍(53 条绝对 URL + 12 条相对引用 + 9 个 setter,零分歧);
286
+ 已知差异:`blob:` 的 `origin` 为 `'null'`、域名不做 UTS-46 映射
287
+ - `assert` / `assert/strict`:**partial** —— 错误字段与 Node 逐项一致;
288
+ 差异块用「公共前后缀 diff」,对单点差异与 Node 逐字一致;
289
+ 唯一消息差异是 `assert.ok` 失败时 Node 附的调用处源码表达式(取不到)
290
+ - `child_process`:**partial** —— `exec`/`execSync`/`execFile`/`execFileSync`/`spawn`/`spawnSync` 与
291
+ Node 的错误形态一致;但宿主是同步 bridge,**`spawn` 先跑完再发事件**(无真并发、长驻进程会阻塞),
292
+ 输出按 UTF-8 解码(二进制有损),`fork` 未实现
293
+ - `path/win32`:**partial**,见「已知偏差」
294
+ - `fs`、`fs/promises`:**partial**
295
+ - Node 语义层(选项解析、flag、错误码、返回值形状)已与本机 Node 的 `fs` 逐项对拍通过
296
+ - fd 系列(`openSync`/`readSync`/`writeSync`/`closeSync`/`fstatSync`/`ftruncateSync`/`fsyncSync`)、
297
+ 回调形式、`fs/promises.open` 返回的 `FileHandle` 均已与 Node 对拍通过
298
+ - `createReadStream` / `createWriteStream` 已与 Node 对拍通过;
299
+ 读流是"按需整块读 + 按 `highWaterMark` 切片"(**没有流式的内存特性**),`'open'` 事件参数为 `null`(无真实 fd)
300
+ - **Java 驱动尚未在真机验证**;已知近似:`atime`/`ctime`/`birthtime` 取 `mtime`、
301
+ `mode` 为按类型的默认值、`readdir` 不区分符号链接、fd 系列(`open`/`read`/`write`/`close`)未实现
302
+ - `console`:**partial** —— 完整的 Node console API;**输出与 Node 逐字节对拍通过**(含 `%s`/`%d`/`%j`、
303
+ `assert` 只打印不抛错、`group` 缩进)。差异:不指定输出流时写 prelude console;`table` 只覆盖常用形态
304
+ - `util/types` / `sys`:**ready** —— 分别是 `util.types` 与 `util` 的同一个对象(与 Node 一致)
305
+ - `punycode`:**ready** —— 各方法与 Node 的 punycode 对拍一致(含 `ucs2`)
306
+ - `stream/consumers`:**partial** —— `buffer`/`text`/`json`/`arrayBuffer` 可用;
307
+ `blob` 显式抛 `ONJ_UNSUPPORTED`(运行时不提供 Blob)
308
+ - `diagnostics_channel`:**partial** —— 发布订阅完整可用;依赖 AsyncLocalStorage 的
309
+ `bindStore`/`unbindStore`/`runStores` 与 `tracingChannel` 显式抛 `ONJ_UNSUPPORTED`
310
+ - `v8`:**partial** —— 堆统计字段名与 Node 一致,但取的是 **JVM 堆**;
311
+ `serialize`/`deserialize`/`setFlagsFromString` 等 V8 专有能力显式抛 `ONJ_UNSUPPORTED`
312
+ - 其余见 `BUILTINS.json`
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export = _default;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+ /**
3
+ * `assert/strict` 子路径入口:与 `require('assert').strict` 是同一个对象。
4
+ * 它的 equal 等同 strictEqual,deepEqual 等同 deepStrictEqual。
5
+ */
6
+ const assertModule = require("../assert");
7
+ module.exports = assertModule.strict;
@@ -0,0 +1,3 @@
1
+ declare function assert(value: unknown, message?: unknown): void;
2
+ declare const exported: typeof assert & Record<string, unknown>;
3
+ export = exported;