@serveryyswys/node.operit 0.1.5 → 0.1.7

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/index.js CHANGED
@@ -51,7 +51,7 @@ const diagnosticsChannelModule = require("./diagnostics_channel");
51
51
  const streamConsumersModule = require("./stream/consumers");
52
52
  const v8Module = require("./v8");
53
53
  const api = {
54
- version: '0.1.5',
54
+ version: '0.1.7',
55
55
  path: pathModule,
56
56
  'path/posix': pathPosixModule,
57
57
  'path/win32': pathWin32Module,
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 让 class 写法的构造器**兼容老式"直接调用父类"用法**。
3
+ *
4
+ * 背景(真实故障):
5
+ * 很多老包写
6
+ * function PNG(options) { Stream.call(this, options); }
7
+ * util.inherits(PNG, Stream);
8
+ * 这在 Node 上完全合法 —— Node 的 Stream / EventEmitter / Readable 都是**普通函数**,
9
+ * 不用 new 也能调用。而本库这些类是用 class 写的,class 必须 new 才会执行构造体,
10
+ * 在 QuickJS 上抛的正是 "class constructors must be invoked with 'new'"。
11
+ *
12
+ * 做法:
13
+ * - 有 this(即 X.call(this)):把"构造器对实例做的初始化"作用到调用者的 this 上,
14
+ * 然后返回这个 this。**不碰原型链** —— 调用方自己的 util.inherits 已经接好了,
15
+ * 我们改反而会破坏它。
16
+ * - 没有 this(严格模式下裸调):按 Node 的宽松语义,等价于 new 一个。
17
+ *
18
+ * 之所以能这样"重放初始化":本库这些类的状态都是按对象惰性创建的
19
+ * (stateOf(this)),初始化就是一次纯函数式调用,不依赖 class 的 this 绑定。
20
+ *
21
+ * **适用范围**:只给"初始化就等于整个构造函数体"的类用。
22
+ * 目前用了两处 —— events.EventEmitter(构造体就是 stateOf(this))与
23
+ * stream.Stream(自己没有构造函数,直接继承 EventEmitter)。
24
+ *
25
+ * 构造函数还做别的事的类**不能**套这个包装:Readable/Writable 要在构造时搬运
26
+ * options.read / options.destroy 等,走包装会漏掉那一步。那些类目前仍然
27
+ * 只能 new —— 这是已知缺口,不是遗漏。
28
+ */
29
+ export declare function makeLegacyCallable<T extends object>(Class: new (...args: never[]) => T, name: string, initialize: (self: object, args: unknown[]) => void): new (...args: never[]) => T;
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeLegacyCallable = makeLegacyCallable;
4
+ /**
5
+ * 让 class 写法的构造器**兼容老式"直接调用父类"用法**。
6
+ *
7
+ * 背景(真实故障):
8
+ * 很多老包写
9
+ * function PNG(options) { Stream.call(this, options); }
10
+ * util.inherits(PNG, Stream);
11
+ * 这在 Node 上完全合法 —— Node 的 Stream / EventEmitter / Readable 都是**普通函数**,
12
+ * 不用 new 也能调用。而本库这些类是用 class 写的,class 必须 new 才会执行构造体,
13
+ * 在 QuickJS 上抛的正是 "class constructors must be invoked with 'new'"。
14
+ *
15
+ * 做法:
16
+ * - 有 this(即 X.call(this)):把"构造器对实例做的初始化"作用到调用者的 this 上,
17
+ * 然后返回这个 this。**不碰原型链** —— 调用方自己的 util.inherits 已经接好了,
18
+ * 我们改反而会破坏它。
19
+ * - 没有 this(严格模式下裸调):按 Node 的宽松语义,等价于 new 一个。
20
+ *
21
+ * 之所以能这样"重放初始化":本库这些类的状态都是按对象惰性创建的
22
+ * (stateOf(this)),初始化就是一次纯函数式调用,不依赖 class 的 this 绑定。
23
+ *
24
+ * **适用范围**:只给"初始化就等于整个构造函数体"的类用。
25
+ * 目前用了两处 —— events.EventEmitter(构造体就是 stateOf(this))与
26
+ * stream.Stream(自己没有构造函数,直接继承 EventEmitter)。
27
+ *
28
+ * 构造函数还做别的事的类**不能**套这个包装:Readable/Writable 要在构造时搬运
29
+ * options.read / options.destroy 等,走包装会漏掉那一步。那些类目前仍然
30
+ * 只能 new —— 这是已知缺口,不是遗漏。
31
+ */
32
+ function makeLegacyCallable(Class, name, initialize) {
33
+ const legacy = function legacyConstructor(...args) {
34
+ if (this === undefined || this === null) {
35
+ // 严格模式下的裸调:按 Node 的宽松语义等价于 new 一个
36
+ return Reflect.construct(Class, args, Class);
37
+ }
38
+ // X.call(this):把初始化重放到调用者给的 this 上。
39
+ //
40
+ // 这里**刻意**不区分 new 与 .call —— 本包装只用于"初始化就等于构造函数体"
41
+ // 的类(EventEmitter 是 stateOf(this),Stream 直接继承 EventEmitter)。
42
+ // 对构造函数还做别的事的类(Readable/Writable 要搬运 options),
43
+ // 这样写会漏掉那部分,所以那些类不套这个包装 —— 见文件末尾的说明。
44
+ initialize(this, args);
45
+ return this;
46
+ };
47
+ // 原型指向 class:instanceof 与 util.inherits(X, 这个) 都能成立
48
+ legacy.prototype = Class.prototype;
49
+ Object.defineProperty(legacy, 'name', { value: name, configurable: true });
50
+ // 静态成员搬过去(defaultMaxListeners / once / on 之类)
51
+ for (const key of Object.getOwnPropertyNames(Class)) {
52
+ if (key === 'length' || key === 'name' || key === 'prototype') {
53
+ continue;
54
+ }
55
+ const descriptor = Object.getOwnPropertyDescriptor(Class, key);
56
+ if (descriptor !== undefined) {
57
+ Object.defineProperty(legacy, key, descriptor);
58
+ }
59
+ }
60
+ return legacy;
61
+ }
package/dist/stream.d.ts CHANGED
@@ -81,4 +81,14 @@ declare class Stream extends EventEmitter {
81
81
  static isReadable: typeof isReadableStream;
82
82
  static isWritable: typeof isWritableStream;
83
83
  }
84
- export = Stream;
84
+ /**
85
+ * 运行期导出**可调用包装**。
86
+ *
87
+ * 老包(pngjs 等)写 `function PNG() { Stream.call(this); } util.inherits(PNG, Stream);` ——
88
+ * Node 的 Stream 是普通函数所以合法,class 不行(QuickJS 会抛
89
+ * "class constructors must be invoked with 'new'")。Stream 自己没有构造函数,
90
+ * 初始化就是 EventEmitter 那一份,所以直接转调。
91
+ * 类型仍标注为 class,静态成员(Readable/Writable/…)由包装层原样拷贝。
92
+ */
93
+ declare const StreamExport: typeof Stream;
94
+ export = StreamExport;
package/dist/stream.js CHANGED
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+ const legacy_callable_1 = require("./lib/legacy-callable");
2
3
  /**
3
4
  * Node stream 模块的移植:Readable / Writable / Duplex / Transform / PassThrough,
4
5
  * 以及 pipeline / finished(回调与 Promise 两种)。
@@ -82,19 +83,68 @@ function decodeChunk(chunk, encoding) {
82
83
  return encoding === null ? '' : buffer_1.Buffer.from(chunk).toString(encoding);
83
84
  }
84
85
  // ------------------------------------------------------------------ Readable
86
+ /**
87
+ * 各流类的"初始化" —— 与构造函数体**逐字等价**。
88
+ *
89
+ * 抽出来的唯一原因:老包写 `Readable.call(this, opts)` 这种继承方式
90
+ * (Node 的 Readable 是普通函数,class 不是)。把构造体独立成函数后,
91
+ * 老式调用路径可以把它重放到调用者给的 this 上,效果与 new 完全一致。
92
+ * 见 lib/legacy-callable.ts。
93
+ */
94
+ function initReadable(self, options) {
95
+ EventEmitter.call(self);
96
+ // 类字段声明(readable = true)也是构造的一部分 —— 抽初始化时最容易漏掉的就是它
97
+ self.readable = true;
98
+ readableStateOf(self, options);
99
+ if (options !== undefined) {
100
+ if (typeof options.read === 'function') {
101
+ self._read = options.read;
102
+ }
103
+ if (typeof options.destroy === 'function') {
104
+ self._destroy = options.destroy;
105
+ }
106
+ }
107
+ }
108
+ function initWritable(self, options) {
109
+ EventEmitter.call(self);
110
+ // 同上:Writable / Duplex 里都有 writable = true 的类字段声明
111
+ self.writable = true;
112
+ writableStateOf(self, options);
113
+ if (options !== undefined) {
114
+ if (typeof options.write === 'function') {
115
+ self._write = options.write;
116
+ }
117
+ if (typeof options.final === 'function') {
118
+ self._final = options.final;
119
+ }
120
+ if (typeof options.destroy === 'function') {
121
+ self._destroy = options.destroy;
122
+ }
123
+ }
124
+ }
125
+ function initDuplex(self, options) {
126
+ initReadable(self, options);
127
+ initWritable(self, options);
128
+ }
129
+ function initTransform(self, options) {
130
+ initDuplex(self, options);
131
+ if (options !== undefined) {
132
+ if (typeof options.transform === 'function') {
133
+ self._transform = options.transform;
134
+ }
135
+ if (typeof options.flush === 'function') {
136
+ self._flush = options.flush;
137
+ }
138
+ }
139
+ }
140
+ function initPassThrough(self, options) {
141
+ initTransform(self, options);
142
+ }
85
143
  class Readable extends EventEmitter {
86
144
  constructor(options) {
87
145
  super();
88
146
  this.readable = true;
89
- readableStateOf(this, options);
90
- if (options !== undefined) {
91
- if (typeof options.read === 'function') {
92
- this._read = options.read;
93
- }
94
- if (typeof options.destroy === 'function') {
95
- this._destroy = options.destroy;
96
- }
97
- }
147
+ initReadable(this, options);
98
148
  }
99
149
  // 子类覆写
100
150
  _read(size) {
@@ -601,18 +651,7 @@ class Writable extends EventEmitter {
601
651
  constructor(options) {
602
652
  super();
603
653
  this.writable = true;
604
- writableStateOf(this, options);
605
- if (options !== undefined) {
606
- if (typeof options.write === 'function') {
607
- this._write = options.write;
608
- }
609
- if (typeof options.final === 'function') {
610
- this._final = options.final;
611
- }
612
- if (typeof options.destroy === 'function') {
613
- this._destroy = options.destroy;
614
- }
615
- }
654
+ initWritable(this, options);
616
655
  }
617
656
  }
618
657
  function applyWritable(target) {
@@ -627,15 +666,7 @@ class Duplex extends Readable {
627
666
  constructor(options) {
628
667
  super(options);
629
668
  this.writable = true;
630
- writableStateOf(this, options);
631
- if (options !== undefined) {
632
- if (typeof options.write === 'function') {
633
- this._write = options.write;
634
- }
635
- if (typeof options.final === 'function') {
636
- this._final = options.final;
637
- }
638
- }
669
+ initWritable(this, options);
639
670
  }
640
671
  }
641
672
  applyWritable(Duplex.prototype);
@@ -643,14 +674,7 @@ applyWritable(Duplex.prototype);
643
674
  class Transform extends Duplex {
644
675
  constructor(options) {
645
676
  super(options);
646
- if (options !== undefined) {
647
- if (typeof options.transform === 'function') {
648
- this._transform = options.transform;
649
- }
650
- if (typeof options.flush === 'function') {
651
- this._flush = options.flush;
652
- }
653
- }
677
+ initTransform(this, options);
654
678
  }
655
679
  _transform(chunk, encoding, callback) {
656
680
  void chunk;
@@ -872,4 +896,27 @@ Stream.finished = finished;
872
896
  Stream.promises = { pipeline: pipelinePromise, finished: finishedPromise };
873
897
  Stream.isReadable = isReadableStream;
874
898
  Stream.isWritable = isWritableStream;
875
- module.exports = Stream;
899
+ /**
900
+ * 运行期导出**可调用包装**。
901
+ *
902
+ * 老包(pngjs 等)写 `function PNG() { Stream.call(this); } util.inherits(PNG, Stream);` ——
903
+ * Node 的 Stream 是普通函数所以合法,class 不行(QuickJS 会抛
904
+ * "class constructors must be invoked with 'new'")。Stream 自己没有构造函数,
905
+ * 初始化就是 EventEmitter 那一份,所以直接转调。
906
+ * 类型仍标注为 class,静态成员(Readable/Writable/…)由包装层原样拷贝。
907
+ */
908
+ const StreamExport = (0, legacy_callable_1.makeLegacyCallable)(Stream, 'Stream', (self) => { EventEmitter.call(self); });
909
+ const ReadableExport = (0, legacy_callable_1.makeLegacyCallable)(Readable, 'Readable', (self, args) => { initReadable(self, args[0]); });
910
+ const WritableExport = (0, legacy_callable_1.makeLegacyCallable)(Writable, 'Writable', (self, args) => { initWritable(self, args[0]); });
911
+ const DuplexExport = (0, legacy_callable_1.makeLegacyCallable)(Duplex, 'Duplex', (self, args) => { initDuplex(self, args[0]); });
912
+ const TransformExport = (0, legacy_callable_1.makeLegacyCallable)(Transform, 'Transform', (self, args) => { initTransform(self, args[0]); });
913
+ const PassThroughExport = (0, legacy_callable_1.makeLegacyCallable)(PassThrough, 'PassThrough', (self, args) => { initPassThrough(self, args[0]); });
914
+ // 静态槽统一指向包装:包装层会从 class 拷贝静态成员,那些槽会指回 class,
915
+ // 于是"模块上是包装、类上是 class"两套并存 —— 这里全部改成包装,保持一致。
916
+ StreamExport.Readable = ReadableExport;
917
+ StreamExport.Writable = WritableExport;
918
+ StreamExport.Duplex = DuplexExport;
919
+ StreamExport.Transform = TransformExport;
920
+ StreamExport.PassThrough = PassThroughExport;
921
+ StreamExport.Stream = StreamExport;
922
+ module.exports = StreamExport;
@@ -1,5 +1,5 @@
1
- export declare class StringDecoder {
2
- static StringDecoder: typeof StringDecoder;
1
+ declare class StringDecoderImpl {
2
+ static StringDecoder: typeof StringDecoderImpl;
3
3
  readonly encoding: string;
4
4
  private pending;
5
5
  constructor(encoding?: string);
@@ -13,3 +13,5 @@ export declare class StringDecoder {
13
13
  private writeUtf16;
14
14
  private writeBase64;
15
15
  }
16
+ declare const StringDecoderExport: typeof StringDecoderImpl;
17
+ export { StringDecoderExport as StringDecoder };
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.StringDecoder = void 0;
37
+ const legacy_callable_1 = require("./lib/legacy-callable");
37
38
  /**
38
39
  * Node string_decoder 模块的移植。
39
40
  *
@@ -93,10 +94,17 @@ function completePrefixLength(bytes) {
93
94
  }
94
95
  return bytes.length;
95
96
  }
96
- class StringDecoder {
97
+ /**
98
+ * 各字段的初始化 —— 与构造函数体逐字等价,供老式 `StringDecoder.call(this)` 重放。
99
+ * 见 lib/legacy-callable.ts。
100
+ */
101
+ function initStringDecoder(self, encoding) {
102
+ self.encoding = normalizeEncoding(encoding);
103
+ self.pending = new Uint8Array(0);
104
+ }
105
+ class StringDecoderImpl {
97
106
  constructor(encoding) {
98
- this.encoding = normalizeEncoding(encoding);
99
- this.pending = new Uint8Array(0);
107
+ initStringDecoder(this, encoding);
100
108
  }
101
109
  get lastNeed() {
102
110
  if (this.pending.length === 0) {
@@ -211,8 +219,9 @@ class StringDecoder {
211
219
  return bytesCodec.encodeBase64(merged.subarray(0, usable));
212
220
  }
213
221
  }
214
- exports.StringDecoder = StringDecoder;
215
- StringDecoder.StringDecoder = StringDecoder;
222
+ // 自引用静态(Node 的 string_decoder.StringDecoder 指向自己);
223
+ // 包装层会把它拷过去,随后改指包装本身。
224
+ StringDecoderImpl.StringDecoder = StringDecoderImpl;
216
225
  function hexOf(buffer) {
217
226
  const digits = '0123456789abcdef';
218
227
  let out = '';
@@ -235,3 +244,7 @@ function asciiOf(buffer) {
235
244
  }
236
245
  return out;
237
246
  }
247
+ const StringDecoderExport = (0, legacy_callable_1.makeLegacyCallable)(StringDecoderImpl, 'StringDecoder', (self, args) => { initStringDecoder(self, args[0]); });
248
+ exports.StringDecoder = StringDecoderExport;
249
+ // 同 events:包装层拷贝静态成员会把自引用指回 class,改指包装
250
+ StringDecoderExport.StringDecoder = StringDecoderExport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serveryyswys/node.operit",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "为 Operit 的 CommonJS 运行时补齐 Node 核心能力(fs / path / os / buffer / ...)",
5
5
  "license": "Apache-2.0",
6
6
  "author": "serveryyswys",