diff --git a/HOWTO.md b/HOWTO.md index 0dca3da0..d98aab23 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -72,14 +72,14 @@ Node.js event emitters take strings as event names and don't check listener sign If you provide an instance of `Event` abstract string type where an event name is expected in any `EventEmitter` method, then the listener type will be unified with `T` and thus provide type checking and inference for the listener function. -We provide [@:enum abstract types](http://haxe.org/manual/types-abstract-enum.html) that enumerate possible event names for a given event emitter. They are implicitly castable to `Event` and can be used for type-checking listener functions as described above. For each `EventEmitter` subclass, an `@:enum abstract` type must be created with a `Event` postfix in its name. For example, if we have a `Process` class which is an `EventEmitter`, it should have a pairing `ProcessEvent` type in its module, i.e.: +We provide [enum abstract types](https://haxe.org/manual/types-abstract-enum.html) that enumerate possible event names for a given event emitter. They are implicitly castable to `Event` and can be used for type-checking listener functions as described above. For each `EventEmitter` subclass, an `enum abstract` type must be created with a `Event` postfix in its name. For example, if we have a `Process` class which is an `EventEmitter`, it should have a pairing `ProcessEvent` type in its module, i.e.: ```haxe extern class Process extends EventEmitter { // ... } -@:enum abstract ProcessEvent(Event) to Event { +enum abstract ProcessEvent(Event) to Event { var Exit : ProcessEventVoid> = "exit"; } ``` @@ -96,7 +96,7 @@ TODO (describe the difference of overloading/optional argument concepts and advi The whole idea of haxe externs is provide a fully type-checked access to external API. Considering that, we must avoid the need for use `Dynamic` type or `cast` and think of a way to properly express type restrictions. -On the other hand, we want developers to be able to copy-paste node.js code into haxe with minimal modification and have it compiling. For that reason we have to weaken some typing restrictions, for example adding implicit cast `from String` for our `@:enum abstract` types. +On the other hand, we want developers to be able to copy-paste node.js code into haxe with minimal modification and have it compiling. For that reason we have to weaken some typing restrictions, for example adding implicit cast `from String` for our `enum abstract` types. ### Multiple inheritance @@ -147,12 +147,12 @@ If a type can be of 3 and more types, nested `EitherType` can be used. ### Constant enumeration -If there's a finite set of posible values for a function argument or object field, [@:enum abstract types](http://haxe.org/manual/types-abstract-enum.html) are used to enumerate those values. +If there's a finite set of posible values for a function argument or object field, [enum abstract types](https://haxe.org/manual/types-abstract-enum.html) are used to enumerate those values. Example: ```haxe -@:enum abstract SymlinkType(String) from String to String { +enum abstract SymlinkType(String) from String to String { var File = "file"; var Dir = "dir"; var Junction = "junction"; @@ -164,10 +164,10 @@ The `to` and `from` implicit cast must be added so user can use both enumeration Constant names are `UpperCamelCase` and their values are actual values expected by native API. -Note that combined with `haxe.EitherType` (described above), `@:enum abstract`s can handle even complicated cases where a value can be of different types, e.g. +Note that combined with `haxe.EitherType` (described above), `enum abstract`s can handle even complicated cases where a value can be of different types, e.g. ```haxe -@:enum abstract ListeningEventAddressType(haxe.EitherType) to haxe.EitherType { +enum abstract ListeningEventAddressType(haxe.EitherType) to haxe.EitherType { var TCPv4 = 4; var TCPv6 = 6; var Unix = -1; @@ -213,4 +213,4 @@ extern class NotSoDeprecated { ## Tricks and hints -TODO (dealing with keywords, `untyped __js__`, inline methods and properties on extern classes) +TODO (dealing with keywords, `js.Syntax.code`, inline methods and properties on extern classes) diff --git a/README.md b/README.md index 61f557c7..ab9c921e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![Haxelib License](https://badgen.net/haxelib/license/hxnodejs)](LICENSE.md) Extern type definitions for Node.JS. Haxe **4.0** or newer is required. +Targeted at **Node.js 24** Active LTS APIs (bindings may lag behind edge cases). Haxe-generated API documentation is available at http://haxefoundation.github.io/hxnodejs/js/Node.html. diff --git a/haxelib.json b/haxelib.json index f03be13b..7ec06077 100644 --- a/haxelib.json +++ b/haxelib.json @@ -4,7 +4,7 @@ "description": "Extern definitions for node.js", "license": "MIT", "version": "12.2.0", - "releasenote": "Update some API, fix some deprecation warnings.", + "releasenote": "Node.js 24 Active LTS audit ongoing; Haxe 4.0+ only.", "classPath": "src", "contributors": ["nadako", "Simn", "Gama11", "HaxeFoundation"], "tags": ["js", "nodejs", "async", "net", "web", "extern"] diff --git a/src/js/Node.hx b/src/js/Node.hx index be786d76..ee053ba2 100644 --- a/src/js/Node.hx +++ b/src/js/Node.hx @@ -24,15 +24,13 @@ package js; import haxe.Constraints.Function; import haxe.extern.Rest; +import js.Syntax.code; import js.node.Module; import js.node.Process; import js.node.Timers.Immediate; import js.node.Timers.Timeout; import js.node.console.Console; import js.node.perf_hooks.Performance; -#if haxe4 -import js.Syntax.code; -#end /** Node.js globals @@ -45,11 +43,7 @@ extern class Node { static var __dirname(get, never):String; private static inline function get___dirname():String { - #if haxe4 return code("__dirname"); - #else - return untyped __js__("__dirname"); - #end } /** @@ -58,11 +52,7 @@ extern class Node { static var __filename(get, never):String; private static inline function get___filename():String { - #if haxe4 return code("__filename"); - #else - return untyped __js__("__filename"); - #end } /** @@ -86,11 +76,7 @@ extern class Node { static var console(get, never):Console; private static inline function get_console():Console { - #if haxe4 return code("console"); - #else - return untyped __js__("console"); - #end } /** @@ -99,11 +85,7 @@ extern class Node { static var exports(get, never):Dynamic; private static inline function get_exports():Dynamic { - #if haxe4 return code("exports"); - #else - return untyped __js__("exports"); - #end } /** @@ -124,11 +106,7 @@ extern class Node { static var globalThis(get, never):Dynamic; private static inline function get_globalThis():Dynamic { - #if haxe4 return code("globalThis"); - #else - return untyped __js__("globalThis"); - #end } /** @@ -137,11 +115,7 @@ extern class Node { static var module(get, never):Module; private static inline function get_module():Module { - #if haxe4 return code("module"); - #else - return untyped __js__("module"); - #end } /** @@ -150,11 +124,7 @@ extern class Node { static var process(get, never):Process; private static inline function get_process():Process { - #if haxe4 return code("process"); - #else - return untyped __js__("process"); - #end } /** @@ -167,11 +137,7 @@ extern class Node { static var performance(get, never):Performance; private static inline function get_performance():Performance { - #if haxe4 return code("performance"); - #else - return untyped __js__("performance"); - #end } /** @@ -188,11 +154,7 @@ extern class Node { This variable may appear to be global but is not. See [require()](https://nodejs.org/api/modules.html#modules_require_id). **/ static inline function require(module:String):Dynamic { - #if haxe4 return code("require({0})", module); - #else - return untyped __js__("require({0})", module); - #end } /** diff --git a/src/js/node/Constants.hx b/src/js/node/Constants.hx index 790b1ec6..a966f665 100644 --- a/src/js/node/Constants.hx +++ b/src/js/node/Constants.hx @@ -22,6 +22,15 @@ package js.node; +/** + Constants exported by Node.js core modules (legacy aggregate module). + + Prefer module-specific constants (e.g. `fs.constants`, `os.constants`, `crypto.constants`) + over `require('constants')`. This extern only mirrors a subset historically used by + crypto engine/padding callers. + + @see https://nodejs.org/api/crypto.html#crypto-constants +**/ @:jsRequire("constants") extern class Constants { static var ENGINE_METHOD_RSA(default, null):Int; diff --git a/src/js/node/Events.hx b/src/js/node/Events.hx index 2afe837c..99451599 100644 --- a/src/js/node/Events.hx +++ b/src/js/node/Events.hx @@ -1,107 +1,180 @@ -/* - * Copyright (C)2014-2020 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -package js.node; - -import haxe.Constraints.Function; -import haxe.extern.Rest; -import js.node.events.EventEmitter; -#if haxe4 -import js.lib.Promise; -import js.lib.Symbol; -#else -import js.Promise; -#end - -/** - Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture - in which certain kinds of objects (called "emitters") emit named events that cause `Function` objects - ("listeners") to be called. - - @see https://nodejs.org/api/events.html#events_events - */ -@:jsRequire("events") -extern class Events { - /** - This symbol shall be used to install a listener for only monitoring `'error'` - events. Listeners installed using this symbol are called before the regular - `'error'` listeners are called. - - @see https://nodejs.org/api/events.html#eventserrormonitor - **/ - #if haxe4 - static final errorMonitor:Symbol; - #else - static var errorMonitor(default, never):Dynamic; - #end - - /** - Value: `Symbol.for('nodejs.rejection')` - - @see https://nodejs.org/api/events.html#eventscapturerejectionsymbol - **/ - #if haxe4 - static final captureRejectionSymbol:Symbol; - #else - static var captureRejectionSymbol(default, never):Dynamic; - #end - - /** - Creates a `Promise` that is resolved when the `EventEmitter` emits the given - event or that is rejected when the `EventEmitter` emits `'error'`. - The `Promise` will resolve with an array of all the arguments emitted to the - given event. - - @see https://nodejs.org/api/events.html#events_events_once_emitter_name - **/ - static function once(emitter:IEventEmitter, name:Event):Promise>; - - /** - Returns a copy of the array of listeners for the event named `name`. - - @see https://nodejs.org/api/events.html#eventsgeteventlistenersemitter-name - **/ - static function getEventListeners(emitter:IEventEmitter, name:Event):Array; - - /** - Change the default `maxListeners` value for all `EventEmitter` instances, - and optionally apply that change to the given emitters. - - @see https://nodejs.org/api/events.html#eventssetmaxlistenersn-eventtargets - **/ - static function setMaxListeners(n:Int, emitters:Rest):Void; - - /** - Returns the currently set max amount of listeners for the given emitter. - - @see https://nodejs.org/api/events.html#eventsgetmaxlistenersemitterortarget - **/ - static function getMaxListeners(emitter:IEventEmitter):Int; - - /** - Returns the number of listeners for the given `eventName` registered on the - given `emitter`. - - @see https://nodejs.org/api/events.html#eventslistenercountemitterortarget-eventname - **/ - static function listenerCount(emitter:IEventEmitter, eventName:Event):Int; -} +/* + * Copyright (C)2014-2020 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.node; + +import haxe.Constraints.Function; +import haxe.extern.Rest; +import js.lib.Promise; +import js.lib.Symbol; +import js.node.events.EventEmitter; +import js.node.web.AbortSignal; + +/** + Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture + in which certain kinds of objects (called "emitters") emit named events that cause `Function` objects + ("listeners") to be called. + + @see https://nodejs.org/api/events.html#events_events + */ +@:jsRequire("events") +extern class Events { + /** + This symbol shall be used to install a listener for only monitoring `'error'` + events. Listeners installed using this symbol are called before the regular + `'error'` listeners are called. + + @see https://nodejs.org/api/events.html#eventserrormonitor + **/ + static final errorMonitor:Symbol; + + /** + Value: `Symbol.for('nodejs.rejection')` + + @see https://nodejs.org/api/events.html#eventscapturerejectionsymbol + **/ + static final captureRejectionSymbol:Symbol; + + /** + Change the default `captureRejections` option on all new `EventEmitter` objects. + + @see https://nodejs.org/api/events.html#eventscapturerejections + **/ + static var captureRejections:Bool; + + /** + By default, a maximum of `10` listeners can be registered for any single event. + This alias mirrors `EventEmitter.defaultMaxListeners`. + + @see https://nodejs.org/api/events.html#eventsdefaultmaxlisteners + **/ + static var defaultMaxListeners:Int; + + /** + Creates a `Promise` that is fulfilled when the `EventEmitter` emits the given + event or that is rejected if the `EventEmitter` emits `'error'` while waiting. + The `Promise` will resolve with an array of all the arguments emitted to the + given event. + + @see https://nodejs.org/api/events.html#eventsonceemitter-name-options + **/ + @:overload(function(emitter:IEventEmitter, name:Event, options:EventsOnceOptions):Promise> {}) + static function once(emitter:IEventEmitter, name:Event):Promise>; + + /** + Returns an `AsyncIterator` that iterates `eventName` events emitted by the `emitter`. + + @see https://nodejs.org/api/events.html#eventsonemitter-eventname-options + **/ + @:overload(function(emitter:IEventEmitter, eventName:Event, options:EventsOnOptions):EventsAsyncIterator {}) + static function on(emitter:IEventEmitter, eventName:Event):EventsAsyncIterator; + + /** + Listens once to the `abort` event on the provided `signal`. + + Returns a disposable that removes the abort listener when disposed. + + @see https://nodejs.org/api/events.html#eventsaddabortlistenersignal-listener + **/ + static function addAbortListener(signal:AbortSignal, listener:Function):EventsDisposable; + + /** + Returns a copy of the array of listeners for the event named `name`. + + @see https://nodejs.org/api/events.html#eventsgeteventlistenersemitter-name + **/ + static function getEventListeners(emitter:IEventEmitter, name:Event):Array; + + /** + Change the default `maxListeners` value for all `EventEmitter` instances, + and optionally apply that change to the given emitters. + + @see https://nodejs.org/api/events.html#eventssetmaxlistenersn-eventtargets + **/ + static function setMaxListeners(n:Int, emitters:Rest):Void; + + /** + Returns the currently set max amount of listeners for the given emitter. + + @see https://nodejs.org/api/events.html#eventsgetmaxlistenersemitterortarget + **/ + static function getMaxListeners(emitter:IEventEmitter):Int; + + /** + Returns the number of listeners for the given `eventName` registered on the + given `emitter`. + + @see https://nodejs.org/api/events.html#eventslistenercountemitterortarget-eventname + **/ + static function listenerCount(emitter:IEventEmitter, eventName:Event):Int; +} + +/** + Options for `Events.once`. +**/ +typedef EventsOnceOptions = { + /** + An `AbortSignal` that can be used to cancel waiting for the event. + **/ + @:optional var signal:AbortSignal; +} + +/** + Options for `Events.on`. +**/ +typedef EventsOnOptions = { + /** + Can be used to cancel awaiting events. + **/ + @:optional var signal:AbortSignal; + + /** + Names of events that will end the iteration. + **/ + @:optional var close:Array; + + /** + The high watermark. The emitter is paused every time the size of events + being buffered is higher than it. + **/ + @:optional var highWaterMark:Int; + + /** + The low watermark. The emitter is resumed every time the size of events + being buffered is lower than it. + **/ + @:optional var lowWaterMark:Int; +} + +/** + Minimal async iterator surface used by `Events.on` (for `for await...of`). +**/ +typedef EventsAsyncIterator = { + function next():Promise<{done:Bool, ?value:Array}>; +} + +/** + Disposable returned by `Events.addAbortListener`. +**/ +typedef EventsDisposable = { + function dispose():Void; +} diff --git a/src/js/node/Iterator.hx b/src/js/node/Iterator.hx index d1f4d482..775583fb 100644 --- a/src/js/node/Iterator.hx +++ b/src/js/node/Iterator.hx @@ -1,37 +1,26 @@ -/* - * Copyright (C)2014-2020 Haxe Foundation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -package js.node; - -#if haxe4 -typedef Iterator = js.lib.Iterator; -typedef IteratorStep = js.lib.Iterator.IteratorStep; -#else -typedef Iterator = { - function next():IteratorStep; -} - -typedef IteratorStep = { - done:Bool, - ?value:T -} -#end +/* + * Copyright (C)2014-2020 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.node; + +typedef Iterator = js.lib.Iterator; +typedef IteratorStep = js.lib.Iterator.IteratorStep; diff --git a/src/js/node/Module.hx b/src/js/node/Module.hx index 1cb43429..f739139f 100644 --- a/src/js/node/Module.hx +++ b/src/js/node/Module.hx @@ -22,6 +22,7 @@ package js.node; +import haxe.extern.EitherType; import js.node.url.URL; /** @@ -42,67 +43,61 @@ extern class Module { /** The `module.exports` object is created by the Module system. - Sometimes this is not acceptable; many want their module to be an instance of some class. - To do this, assign the desired export object to `module.exports`. - Assigning the desired object to `exports` will simply rebind the local `exports` variable, which is probably not - what is desired. - - @see https://nodejs.org/api/modules.html#modules_module_exports **/ var exports:Dynamic; /** The fully resolved filename of the module. - - @see https://nodejs.org/api/modules.html#modules_module_filename **/ var filename(default, null):String; /** The identifier for the module. Typically this is the fully resolved filename. - - @see https://nodejs.org/api/modules.html#modules_module_id **/ var id(default, null):String; /** Whether or not the module is done loading, or is in the process of loading. - - @see https://nodejs.org/api/modules.html#modules_module_loaded **/ var loaded(default, null):Bool; /** The module that first required this one. - - @see https://nodejs.org/api/modules.html#modules_module_parent **/ var parent(default, null):Module; /** The search paths for the module. - - @see https://nodejs.org/api/modules.html#modules_module_paths **/ var paths(default, null):Array; + /** + True if the module is running during the Node.js bootstrap process. + **/ + var isPreloading(default, null):Bool; + + /** + The directory name of the module. + **/ + var path(default, null):String; + /** The `module.require()` method provides a way to load a module as if `require()` was called from the original module. - - @see https://nodejs.org/api/modules.html#modules_module_require_id **/ function require(id:String):Dynamic; /** A list of the names of all modules provided by Node.js. - Can be used to verify if a module is maintained by a third party or not. - - @see https://nodejs.org/api/modules.html#modules_module_builtinmodules **/ static var builtinModules(default, null):Array; + /** + Returns `true` if the module is a core/built-in module. + **/ + static function isBuiltin(moduleName:String):Bool; + /** @see https://nodejs.org/api/modules.html#modules_module_createrequire_filename **/ @@ -112,9 +107,87 @@ extern class Module { /** The `module.syncBuiltinESMExports()` method updates all the live bindings for builtin ES Modules to match the properties of the CommonJS exports. - It does not add or remove exported names from the ES Modules. - - @see https://nodejs.org/api/modules.html#modules_module_syncbuiltinesmexports **/ static function syncBuiltinESMExports():Void; + + /** + `findSourceMap` finds the corresponding source map for a given file path. + // TODO(section-5): refine SourceMap type when vm/module source-map types are audited. + **/ + static function findSourceMap(path:String):Null; + + /** + Removes TypeScript type annotations from `code`. + **/ + static function stripTypeScriptTypes(code:String, ?options:ModuleStripTypeScriptTypesOptions):String; + + /** + Register synchronous customization hooks. + // TODO(section-5): refine hook option types when the module loader API is audited. + **/ + static function registerHooks(options:Dynamic):Void; + + /** + Finds the closest `package.json` for the given specifier. + + @see https://nodejs.org/api/module.html#modulefindpackagejsonspecifier-base + **/ + @:overload(function(specifier:URL, ?base:EitherType):Null {}) + static function findPackageJSON(specifier:String, ?base:EitherType):Null; + + /** + Register a module that exports hooks that customize Node.js module resolution and loading. + // TODO(section-5): refine register options / return types when the loader API is audited. + + @see https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options + **/ + @:overload(function(specifier:String, parentURL:EitherType, ?options:Dynamic):Void {}) + static function register(specifier:String, ?options:Dynamic):Void; + + /** + Enable the module compile cache. + + @see https://nodejs.org/api/module.html#moduleenablecompilecachecachedir + **/ + static function enableCompileCache(?cacheDir:String):Dynamic; + + /** + Flush the module compile cache to disk. + **/ + static function flushCompileCache():Void; + + /** + Return the directory where the module compile cache is stored, if enabled. + **/ + static function getCompileCacheDir():Null; + + /** + Enable or disable Source Map v3 support for stack traces. + **/ + static function setSourceMapsSupport(enabled:Bool, ?options:Dynamic):Void; + + /** + Return whether Source Map support is enabled and related options. + **/ + static function getSourceMapsSupport():Dynamic; +} + +/** + Options for `Module.stripTypeScriptTypes`. +**/ +typedef ModuleStripTypeScriptTypesOptions = { + /** + Mode of stripping. Default: `'strip'`. + **/ + @:optional var mode:String; + + /** + Whether to produce source maps. Default: `false`. + **/ + @:optional var sourceMap:Bool; + + /** + The filename used when generating source maps. + **/ + @:optional var sourceUrl:String; } diff --git a/src/js/node/Process.hx b/src/js/node/Process.hx index c59f9d65..52f092f8 100644 --- a/src/js/node/Process.hx +++ b/src/js/node/Process.hx @@ -23,17 +23,16 @@ package js.node; import haxe.DynamicAccess; +import haxe.Constraints.Function; import haxe.extern.EitherType; import haxe.extern.Rest; +import js.lib.Error; import js.node.child_process.ChildProcess.ChildProcessSendOptions; import js.node.events.EventEmitter; -import js.node.stream.Readable; -import js.node.stream.Writable; -#if haxe4 -import js.lib.Error; -#else -import js.Error; -#end +import js.node.process.ProcessFinalization; +import js.node.process.ProcessPermission; +import js.node.stream.Readable.IReadable; +import js.node.stream.Writable.IWritable; /** Enumeration of events emitted by the Process class. @@ -50,14 +49,7 @@ enum abstract ProcessEvent(Event) to Event { var Exit:ProcessEventVoid> = "exit"; /** - Emitted when node empties it's event loop and has nothing else to schedule. - - Normally, node exits when there is no work scheduled, but a listener for `beforeExit` - can make asynchronous calls, and cause node to continue. - - `beforeExit` is not emitted for conditions causing explicit termination, such as `process.exit()` - or uncaught exceptions, and should not be used as an alternative to the `exit` event - unless the intention is to schedule more work. + Emitted when node empties its event loop and has nothing else to schedule. **/ var BeforeExit:ProcessEventVoid> = "beforeExit"; @@ -67,20 +59,47 @@ enum abstract ProcessEvent(Event) to Event { will not occur. **/ var UncaughtException:ProcessEventVoid> = "uncaughtException"; + + /** + This event is emitted before an `'uncaughtException'` event is emitted or a hook installed via + `process.setUncaughtExceptionCaptureCallback()` is called. + **/ + var UncaughtExceptionMonitor:ProcessEventVoid> = "uncaughtExceptionMonitor"; + + /** + Emitted whenever a `Promise` is rejected and no error handler is attached to the promise within a turn of the event loop. + **/ + var UnhandledRejection:ProcessEvent<(reason:Dynamic, promise:js.lib.Promise) -> Void> = "unhandledRejection"; + + /** + Emitted whenever a `Promise` has been rejected and an error handler was attached to it later than after an event loop turn. + **/ + var RejectionHandled:ProcessEvent<(promise:js.lib.Promise) -> Void> = "rejectionHandled"; + + /** + The `process` object emits a `'warning'` event whenever Node.js emits a process warning. + **/ + var Warning:ProcessEvent<(warning:Error) -> Void> = "warning"; + + /** + Emitted when a message is received over IPC. Available for child processes. + **/ + var Message:ProcessEvent<(message:Dynamic, sendHandle:Dynamic) -> Void> = "message"; + + /** + Emitted after calling `process.disconnect()` in a child process. + **/ + var Disconnect:ProcessEventVoid> = "disconnect"; } extern class Process extends EventEmitter { /** A Writable Stream to stdout. - - `stderr` and `stdout` are unlike other streams in Node in that writes to them are usually blocking. **/ var stdout:IWritable; /** A writable stream to stderr. - - `stderr` and `stdout` are unlike other streams in Node in that writes to them are usually blocking. **/ var stderr:IWritable; @@ -91,19 +110,15 @@ extern class Process extends EventEmitter { /** An array containing the command line arguments. - The first element will be `node`, the second element will be the name of the JavaScript file. - The next elements will be any additional command line arguments. - - E.g: - $ node process-2.js one two=three four - 0: node - 1: /Users/mjr/work/node/process-2.js - 2: one - 3: two=three - 4: four **/ var argv:Array; + /** + The `process.argv0` property stores a read-only copy of the original value of `argv[0]` + passed when Node.js starts. + **/ + var argv0(default, null):String; + /** This is the absolute pathname of the executable that started the process. **/ @@ -111,13 +126,14 @@ extern class Process extends EventEmitter { /** This is the set of node-specific command line options from the executable that started the process. - These options do not show up in `argv`, and do not include the node executable, the name of the script, - or any options following the script name. - - These options are useful in order to spawn child processes with the same execution environment as the parent. **/ var execArgv:Array; + /** + If the Node.js process is spawned with an IPC channel, `process.connected` is `true` while connected. + **/ + var connected(default, null):Bool; + /** This causes node to emit an abort. This will cause node to exit and generate a core file. **/ @@ -147,8 +163,6 @@ extern class Process extends EventEmitter { /** A number which will be the process exit code, when the process either exits gracefully, or is exited via `process.exit()` without specifying a code. - - Specifying a code to `process.exit(code)` will override any previous setting of `process.exitCode`. **/ var exitCode:Null; @@ -160,51 +174,55 @@ extern class Process extends EventEmitter { /** Sets the group identity of the process. See setgid(2). - This accepts either a numerical ID or a groupname string. - If a groupname is specified, this method blocks while resolving it to a numerical ID. - - Note: this function is only available on POSIX platforms (i.e. not Windows) **/ @:overload(function(id:String):Void {}) function setgid(id:Int):Void; /** Gets the user identity of the process. See getuid(2). - Note: this function is only available on POSIX platforms (i.e. not Windows) **/ function getuid():Int; /** Sets the user identity of the process. See setuid(2). - This accepts either a numerical ID or a username string. - If a username is specified, this method blocks while resolving it to a numerical ID. - - Note: this function is only available on POSIX platforms (i.e. not Windows) **/ @:overload(function(id:String):Void {}) function setuid(id:Int):Void; + /** + Gets the effective group identity of the process. See getegid(2). + **/ + function getegid():Int; + + /** + Sets the effective group identity of the process. See setegid(2). + **/ + @:overload(function(id:String):Void {}) + function setegid(id:Int):Void; + + /** + Gets the effective user identity of the process. See geteuid(2). + **/ + function geteuid():Int; + + /** + Sets the effective user identity of the process. See seteuid(2). + **/ + @:overload(function(id:String):Void {}) + function seteuid(id:Int):Void; + /** Returns an array with the supplementary group IDs. - POSIX leaves it unspecified if the effective group ID is included but node.js ensures it always is. - Note: this function is only available on POSIX platforms (i.e. not Windows) **/ function getgroups():Array; /** Sets the supplementary group IDs. - This is a privileged operation, meaning you need to be root or have the CAP_SETGID capability. - - Note: this function is only available on POSIX platforms (i.e. not Windows) - The list can contain group IDs, group names or both. **/ function setgroups(groups:Array>):Void; /** - Reads /etc/group and initializes the group access list, using all groups of which the user is a member. - This is a privileged operation, meaning you need to be root or have the CAP_SETGID capability. - - Note: this function is only available on POSIX platforms (i.e. not Windows) + Reads /etc/group and initializes the group access list. **/ function initgroups(user:EitherType, extra_group:EitherType):Void; @@ -220,23 +238,24 @@ extern class Process extends EventEmitter { /** An Object containing the JavaScript representation of the configure options that were used to compile the current node executable. - This is the same as the "config.gypi" file that was produced when running the ./configure script. **/ - var config:Dynamic; + var config:DynamicAccess; /** - Send a signal to a process. - `pid` is the process id and `signal` is the string describing the signal to send. Signal names are strings like 'SIGINT' or 'SIGHUP'. - - If omitted, the `signal` will be 'SIGTERM'. See Signal Events and kill(2) for more information. + IPC channel reference for the process, if present. + // TODO(section-5): refine IPC channel type when child_process IPC is audited. + **/ + var channel(default, null):Null; - Will throw an error if target does not exist, and as a special case, - a signal of 0 can be used to test for the existence of a process. + /** + The debugger port of the Node.js process. + **/ + var debugPort:Int; - Note that just because the name of this function is `kill`, it is really just a signal sender, like the kill system call. - The signal sent may do something other than kill the target process. + /** + Send a signal to a process. **/ - function kill(pid:Int, ?signal:String):Void; + function kill(pid:Int, ?signal:EitherType):Bool; /** The PID of the process. @@ -245,10 +264,6 @@ extern class Process extends EventEmitter { /** Getter/setter to set what is displayed in 'ps'. - - When used as a setter, the maximum length is platform-specific and probably short. - On Linux and OS X, it's limited to the size of the binary name plus the length of the - command line arguments because it overwrites the argv memory. **/ var title:String; @@ -277,25 +292,92 @@ extern class Process extends EventEmitter { **/ var report:Report; + /** + Permission model API when the process is started with `--permission`. + `null` / unavailable when the permission model is not enabled. + **/ + var permission(default, null):Null; + + /** + Provides APIs for registering callbacks invoked during process finalization. + **/ + var finalization(default, null):ProcessFinalization; + + /** + A boolean reflecting whether the current Node.js process is running with `--pending-deprecation` enabled. + **/ + var noDeprecation:Bool; + + /** + Enable logging of deprecation warnings. + **/ + var traceDeprecation:Bool; + + /** + Throw on deprecated API usage. + **/ + var throwDeprecation:Bool; + + /** + A boolean value that indicates whether source maps are enabled for Node stacks. + **/ + var sourceMapsEnabled(default, null):Bool; + + /** + A set of flags from `NODE_OPTIONS` and command-line that Node.js allows. + **/ + var allowedNodeEnvironmentFlags(default, null):js.lib.Set; + + /** + Provides a way to get available features known at compile/runtime. + **/ + var features(default, null):ProcessFeatures; + /** Returns an object describing the memory usage of the Node process measured in bytes. **/ function memoryUsage():MemoryUsage; /** - On the next loop around the event loop call this callback. - This is not a simple alias to setTimeout(fn, 0), it's much more efficient. - It typically runs before any other I/O events fire, but there are some exceptions. + Returns the resident set size (RSS) used by the process in bytes. + **/ + @:native("memoryUsage.rss") + function memoryUsageRss():Float; + + /** + Returns information about the V8 heap spaces and usage of process resources. + **/ + function resourceUsage():ResourceUsage; + + /** + Returns the user and system CPU time usage of the current process, in microseconds. + **/ + function cpuUsage(?previousValue:CpuUsage):CpuUsage; - This is important in developing APIs where you want to give the user the chance to - assign event handlers after an object has been constructed, but before any I/O has occurred. + /** + Gets the amount of free memory that is still available to the process, in bytes. + May return `undefined`/`0` if not supported. + **/ + function availableMemory():Float; + + /** + Gets the amount of memory available to the process (based on cgroup / ulimit etc.). + May return `undefined` if not constrained. + **/ + function constrainedMemory():Float; + + /** + Returns an array of strings naming active resources currently keeping the event loop alive. + **/ + function getActiveResourcesInfo():Array; + + /** + On the next loop around the event loop call this callback. **/ function nextTick(callback:Void->Void, args:Rest):Void; /** Sets or reads the process's file mode creation mask. - Child processes inherit the mask from the parent process. - Returns the old mask if mask argument is given, otherwise returns the current mask. **/ function umask(?mask:Int):Int; @@ -305,64 +387,117 @@ extern class Process extends EventEmitter { function uptime():Float; /** - Returns the current high-resolution real time in a [seconds, nanoseconds] tuple Array. - It is relative to an arbitrary time in the past. - It is not related to the time of day and therefore not subject to clock drift. - The primary use is for measuring performance between intervals. - You may pass in the result of a previous call to `hrtime` to get a diff reading, - useful for benchmarks and measuring intervals + Returns the current high-resolution real time in a `[seconds, nanoseconds]` tuple Array. **/ @:overload(function(prev:Array):Array {}) function hrtime():Array; /** - Alternate way to retrieve require.main. The difference is that if the main module changes at runtime, - require.main might still refer to the original main module in modules that were required - before the change occurred. Generally it's safe to assume that the two refer to the same module. + The `bigint` version of `process.hrtime()` that returns nanoseconds as a `bigint`. + Typed as `Dynamic` for Haxe 4.0.5 compatibility (no `js.lib.BigInt` there). + **/ + @:native("hrtime.bigint") + function hrtimeBigint():Dynamic; - As with require.main, it will be undefined if there was no entry script. + /** + Alternate way to retrieve require.main. + @deprecated Use `Require.main` instead. **/ + @:deprecated var mainModule(default, null):Module; /** Send a message to the parent process. - Only available for child processes. See `ChildProcess.send`. + // TODO(section-5): type `sendHandle` with net.Socket / net.Server / dgram.Socket. **/ - @:overload(function(message:Dynamic, sendHandle:Dynamic, options:ChildProcessSendOptions, ?callback:Error->Void):Bool {}) - @:overload(function(message:Dynamic, sendHandle:Dynamic, ?callback:Error->Void):Bool {}) - function send(message:Dynamic, ?callback:Error->Void):Bool; + @:overload(function(message:Dynamic, sendHandle:Dynamic, options:ChildProcessSendOptions, ?callback:Null->Void):Bool {}) + @:overload(function(message:Dynamic, sendHandle:Dynamic, ?callback:Null->Void):Bool {}) + function send(message:Dynamic, ?callback:Null->Void):Bool; /** Close the IPC channel to parent process. - - Only available for child processes. See `ChildProcess.disconnect`. **/ function disconnect():Void; /** - Disable run-time deprecation warnings. - See `Util.deprecate`. + The `process.emitWarning()` method can be used to emit custom or application specific process warnings. **/ - var noDeprecation:Bool; + @:overload(function(warning:String, ?type:String, ?code:String, ?ctor:Function):Void {}) + @:overload(function(warning:String, options:EmitWarningOptions):Void {}) + function emitWarning(warning:EitherType, ?type:String, ?code:String, ?ctor:Function):Void; /** - Enable logging of deprecation warnings. - See `Util.deprecate`. + Loads environment variables from a `.env` file into `process.env`. **/ - var traceDeprecation:Bool; + function loadEnvFile(?path:String):Void; /** - Throw on deprecated API usage. - See `Util.deprecate`. + Returns the built-in module with the given `id`, or `undefined` if not found. **/ - var throwDeprecation:Bool; + function getBuiltinModule(id:String):Dynamic; + + /** + Sets a user-provided function as the uncaughtException capture callback. + **/ + function setUncaughtExceptionCaptureCallback(fn:NullVoid>):Void; + + /** + Indicates whether a callback has been set using `setUncaughtExceptionCaptureCallback`. + **/ + function hasUncaughtExceptionCaptureCallback():Bool; + + /** + Enable or disable Source Map v3 support for stack traces. + **/ + function setSourceMapsEnabled(value:Bool):Void; + + /** + Reference a value that implements `Symbol.dispose` / ref counting so it keeps the event loop alive. + **/ + function ref(maybeRefable:Dynamic):Void; + + /** + Unreference a previously referenced value. + **/ + function unref(maybeRefable:Dynamic):Void; + + /** + Returns the CPU usage statistics of the current worker thread. + **/ + function threadCpuUsage(?previousValue:CpuUsage):CpuUsage; } typedef MemoryUsage = { rss:Float, heapTotal:Float, - heapUsed:Float + heapUsed:Float, + ?external:Float, + ?arrayBuffers:Float +} + +typedef CpuUsage = { + user:Float, + system:Float +} + +typedef ResourceUsage = { + userCPUTime:Float, + systemCPUTime:Float, + maxRSS:Float, + sharedMemorySize:Float, + unsharedDataSize:Float, + unsharedStackSize:Float, + minorPageFault:Float, + majorPageFault:Float, + swappedOut:Float, + fsRead:Float, + fsWrite:Float, + ipcSent:Float, + ipcReceived:Float, + signalsCount:Float, + voluntaryContextSwitches:Float, + involuntaryContextSwitches:Float } typedef Release = { @@ -372,3 +507,29 @@ typedef Release = { ?libUrl:String, ?lts:String } + +typedef EmitWarningOptions = { + @:optional var type:String; + @:optional var code:String; + @:optional var detail:String; + @:optional var ctor:Function; +} + +/** + Boolean flags describing process feature availability. + + @see https://nodejs.org/api/process.html#processfeatures +**/ +typedef ProcessFeatures = { + var inspector(default, null):Bool; + var debug(default, null):Bool; + var uv(default, null):Bool; + var ipv6(default, null):Bool; + var tls(default, null):Bool; + var tls_alpn(default, null):Bool; + var tls_ocsp(default, null):Bool; + var tls_sni(default, null):Bool; + @:optional var typescript(default, null):EitherType; + @:optional var require_module(default, null):Bool; + @:optional var cached_builtins(default, null):Bool; +} diff --git a/src/js/node/Report.hx b/src/js/node/Report.hx index 8d413738..ce755cc3 100644 --- a/src/js/node/Report.hx +++ b/src/js/node/Report.hx @@ -1,54 +1,63 @@ -package js.node; - -#if haxe4 -import js.lib.Error; -#else -import js.Error; -#end - -extern class Report { - /** - If the reports are written in compact mode. - **/ - var compact:Bool; - - /** - The directory in which the reports are written. - **/ - var directory:String; - - /** - The file in which the reports are written. - **/ - var filename:String; - - /** - Returns the diagnostic report as an object. Optionally from an error object. - **/ - function getReport(?err:Error):Dynamic; - - /** - When the diagnostic report was generated in case of fatal errors. - **/ - var reportOnFatalError:Bool; - - /** - If the diagnostic report was generated by receiving a signal. - **/ - var reportOnSignal:Bool; - - /** - When the diagnostic report was generated in case of a uncaught exception. - **/ - var reportOnUncaughtException:Bool; - - /** - The signal that triggered the diagnostic report. - **/ - var signal:String; - - /** - Writes a diagnostic report to a file. - **/ - function writeReport(?filename:String, ?err:Error):String; -} +package js.node; + +import js.lib.Error; + +/** + Diagnostic report API available via `process.report`. + + @see https://nodejs.org/api/process.html#processreport +**/ +extern class Report { + /** + If the reports are written in compact mode. + **/ + var compact:Bool; + + /** + The directory in which the reports are written. + **/ + var directory:String; + + /** + The file in which the reports are written. + **/ + var filename:String; + + /** + Returns the diagnostic report as an object. Optionally from an error object. + **/ + function getReport(?err:Error):Dynamic; + + /** + When the diagnostic report was generated in case of fatal errors. + **/ + var reportOnFatalError:Bool; + + /** + If the diagnostic report was generated by receiving a signal. + **/ + var reportOnSignal:Bool; + + /** + When the diagnostic report was generated in case of a uncaught exception. + **/ + var reportOnUncaughtException:Bool; + + /** + If `true`, the environment variables are excluded from the report. + Default: `false`. + + @see https://nodejs.org/api/process.html#processreportexcludeenv + **/ + var excludeEnv:Bool; + + /** + The signal that triggered the diagnostic report. + **/ + var signal:String; + + /** + Writes a diagnostic report to a file. + **/ + function writeReport(?filename:String, ?err:Error):String; +} diff --git a/src/js/node/Stream.hx b/src/js/node/Stream.hx index 7c8f2919..a6aa4bd3 100644 --- a/src/js/node/Stream.hx +++ b/src/js/node/Stream.hx @@ -23,17 +23,13 @@ package js.node; import haxe.extern.Rest; -import js.html.AbortSignal; +import js.lib.Error; +import js.lib.Promise; import js.node.events.EventEmitter; +import js.node.stream.Duplex.IDuplex; import js.node.stream.Readable.IReadable; import js.node.stream.Writable.IWritable; -#if haxe4 -import js.lib.Error; -import js.lib.Promise; -#else -import js.Error; -import js.Promise; -#end +import js.node.web.AbortSignal; /** Base class for all streams. @@ -42,6 +38,13 @@ import js.Promise; extern class Stream> extends EventEmitter implements IStream { private function new(); + /** + Promise-based stream helpers (`stream/promises`). + + @see https://nodejs.org/api/stream.html#streams-promises-api + **/ + static var promises(default, never):StreamPromises; + /** A module method to pipe between streams forwarding errors and properly cleaning up and provide a callback when the pipeline is complete. @@ -75,6 +78,46 @@ extern class Stream> extends EventEmitter implements @:overload(function(stream:IStream, options:StreamFinishedOptions, callback:Null->Void):Void->Void {}) static function finished(stream:IStream, ?options:StreamFinishedOptions):Promise; + /** + Combines two or more streams into a `Duplex` stream that writes to the first + stream and reads from the last. + + Pass `StreamComposeOptions` (for example `{signal: ...}`) as the last argument when needed. + + @see https://nodejs.org/api/stream.html#streamcomposestreams + **/ + static function compose(streams:Rest):IDuplex; + + /** + Returns a pair of connected Duplex streams where data written to either side + appears on the other. + + @see https://nodejs.org/api/stream.html#streamduplexpairoptions + **/ + static function duplexPair(?options:js.node.stream.Duplex.DuplexNewOptions):Array; + + /** + Attaches an AbortSignal to a readable or writable stream so destroying + the stream when the signal is aborted. + + @see https://nodejs.org/api/stream.html#streamaddabortsignalsignal-stream + **/ + static function addAbortSignal(signal:AbortSignal, stream:IStream):IStream; + + /** + Returns the default highWaterMark used by streams. + + @see https://nodejs.org/api/stream.html#streamgetdefaulthighwatermarkobjectmode + **/ + static function getDefaultHighWaterMark(objectMode:Bool):Int; + + /** + Sets the default highWaterMark used by streams. + + @see https://nodejs.org/api/stream.html#streamsetdefaulthighwatermarkobjectmode-value + **/ + static function setDefaultHighWaterMark(objectMode:Bool, value:Int):Void; + /** Returns whether the stream is readable. @@ -82,7 +125,7 @@ extern class Stream> extends EventEmitter implements @see https://nodejs.org/api/stream.html#streamisreadablestream **/ - static function isReadable(stream:Dynamic):Null; + static function isReadable(stream:Any):Null; /** Returns whether the stream is writable. @@ -91,14 +134,14 @@ extern class Stream> extends EventEmitter implements @see https://nodejs.org/api/stream.html#streamiswritablestream **/ - static function isWritable(stream:Dynamic):Null; + static function isWritable(stream:Any):Null; /** Returns whether the stream has been destroyed. Exported by the `stream` module (undocumented helper; available since Node 16+). **/ - static function isDestroyed(stream:Dynamic):Bool; + static function isDestroyed(stream:Any):Bool; /** Returns whether the stream has been read from or cancelled. @@ -107,14 +150,14 @@ extern class Stream> extends EventEmitter implements @see https://nodejs.org/api/stream.html#streamreadableisdisturbedstream **/ - static function isDisturbed(stream:Dynamic):Bool; + static function isDisturbed(stream:Any):Bool; /** Returns whether the stream has encountered an error. @see https://nodejs.org/api/stream.html#streamiserroredstream **/ - static function isErrored(stream:Dynamic):Bool; + static function isErrored(stream:Any):Bool; } /** @@ -169,6 +212,16 @@ typedef StreamPipelineOptions = { @:optional var end:Bool; } +/** + Options for `Stream.compose`. +**/ +typedef StreamComposeOptions = { + /** + Allows destroying the stream if the signal is aborted. + **/ + @:optional var signal:AbortSignal; +} + /** `IStream` interface is used as "any Stream". diff --git a/src/js/node/StreamPromises.hx b/src/js/node/StreamPromises.hx index ef3cdcfd..9ed170a0 100644 --- a/src/js/node/StreamPromises.hx +++ b/src/js/node/StreamPromises.hx @@ -23,14 +23,10 @@ package js.node; import haxe.extern.Rest; +import js.lib.Promise; import js.node.Stream; import js.node.stream.Readable.IReadable; import js.node.stream.Writable.IWritable; -#if haxe4 -import js.lib.Promise; -#else -import js.Promise; -#end /** The `stream/promises` API provides an alternative set of asynchronous stream diff --git a/src/js/node/StringDecoder.hx b/src/js/node/StringDecoder.hx index ec8a33a0..2b4157e0 100644 --- a/src/js/node/StringDecoder.hx +++ b/src/js/node/StringDecoder.hx @@ -22,11 +22,7 @@ package js.node; -#if haxe4 import js.lib.ArrayBufferView; -#else -import js.html.ArrayBufferView; -#end /** The `string_decoder` module provides an API for decoding `Buffer` objects into strings in a manner that preserves @@ -56,7 +52,7 @@ extern class StringDecoder { /** Returns a decoded string, ensuring that any incomplete multibyte characters at the end of the `Buffer`, or - `TypedArray`, or `DataViewor` are omitted from the returned string and stored in an internal buffer for the next + `TypedArray`, or `DataView` are omitted from the returned string and stored in an internal buffer for the next call to `stringDecoder.write()` or `stringDecoder.end()`. @see https://nodejs.org/api/string_decoder.html#string_decoder_stringdecoder_write_buffer diff --git a/src/js/node/Timers.hx b/src/js/node/Timers.hx index 4ef3da7e..697678e5 100644 --- a/src/js/node/Timers.hx +++ b/src/js/node/Timers.hx @@ -135,4 +135,11 @@ extern class Timeout { Creating too many of these can adversely impact performance of the Node.js application. **/ function unref():Timeout; + + /** + Cancels the timeout. + + Stability: 3 - Legacy: Use `clearTimeout()` instead. + **/ + function close():Timeout; } diff --git a/src/js/node/TimersPromises.hx b/src/js/node/TimersPromises.hx index 4d43b4b3..010e4327 100644 --- a/src/js/node/TimersPromises.hx +++ b/src/js/node/TimersPromises.hx @@ -22,12 +22,8 @@ package js.node; -import js.node.web.AbortSignal; -#if haxe4 import js.lib.Promise; -#else -import js.Promise; -#end +import js.node.web.AbortSignal; /** The `timers/promises` API provides an alternative set of timer functions that return `Promise` objects. diff --git a/src/js/node/buffer/Buffer.hx b/src/js/node/buffer/Buffer.hx index 41ba2eb7..3ba61693 100644 --- a/src/js/node/buffer/Buffer.hx +++ b/src/js/node/buffer/Buffer.hx @@ -25,16 +25,10 @@ package js.node.buffer; import haxe.extern.EitherType; import haxe.io.Bytes; import haxe.io.UInt8Array; -#if haxe4 import js.lib.ArrayBuffer; import js.lib.ArrayBufferView; import js.lib.Object; import js.lib.Uint8Array; -#else -import js.html.ArrayBuffer; -import js.html.ArrayBufferView; -import js.html.Uint8Array; -#end /** The `Buffer` class is a global type for dealing with binary data directly. It can be constructed in a variety of ways. @@ -94,18 +88,14 @@ extern class Buffer extends Uint8Array { @see https://nodejs.org/api/buffer.html#buffer_class_method_buffer_bytelength_string_encoding **/ - #if (haxe_ver >= 3.3) // it need extern SharedArrayBuffer for Node // @:overload(function(string:SharedArrayBuffer):Int {}) @:overload(function(string:String, ?encoding:String):Int {}) @:overload(function(string:ArrayBufferView):Int {}) @:overload(function(string:ArrayBuffer):Int {}) static function byteLength(string:Buffer):Int; - #end - #if (haxe_ver >= 3.3) - @:deprecated("In haxe 3.3+, use Buffer.byteLength instead!") - #end + @:deprecated("Use Buffer.byteLength instead") inline static function _byteLength(string:String, ?encoding:String):Int return untyped Buffer['byteLength'](string, encoding); @@ -125,6 +115,13 @@ extern class Buffer extends Uint8Array { **/ static function concat(list:Array, ?totalLength:Int):Buffer; + /** + Copies the underlying memory of `view` into a new `Buffer`. + + @see https://nodejs.org/api/buffer.html#static-method-buffercopybytesfromview-offset-length + **/ + static function copyBytesFrom(view:js.lib.ArrayBufferView, ?offset:Int, ?length:Int):Buffer; + /** Allocates a new `Buffer`. @@ -167,14 +164,8 @@ extern class Buffer extends Uint8Array { // buf[index] // var buffer:ArrayBuffer; - /** - When setting `byteOffset` in `Buffer.from(ArrayBuffer, byteOffset, length)` - or sometimes when allocating a buffer smaller than `Buffer.poolSize` the - buffer doesn't start from a zero offset on the underlying `ArrayBuffer`. - - @see https://nodejs.org/api/buffer.html#buffer_buf_byteoffset - **/ - static var byteOffset(default, null):Int; + // `buf.byteOffset` is inherited from `Uint8Array`. + // see https://nodejs.org/api/buffer.html#buffer_buf_byteoffset /** Compares `buf` with `target` and returns a number indicating whether `buf` comes before, after, @@ -414,11 +405,7 @@ extern class Buffer extends Uint8Array { @see https://nodejs.org/api/buffer.html#buffer_buf_subarray_start_end **/ - #if haxe4 function subarray(?start:Int, ?end:Int):Buffer; - #else - override function subarray(start:Int, ?end:Int):Buffer; - #end /** Returns a new `Buffer` that references the same memory as the original, @@ -460,7 +447,7 @@ extern class Buffer extends Uint8Array { @see https://nodejs.org/api/buffer.html#buffer_buf_tojson **/ - function toJSON():Dynamic; + function toJSON():BufferJson; /** Decodes `buf` to a string according to the specified character encoding in `encoding`. @@ -682,6 +669,17 @@ extern class Buffer extends Uint8Array { return BufferModule.kMaxLength; } + /** + An alias for `buffer.constants.MAX_STRING_LENGTH`. + + @see https://nodejs.org/api/buffer.html#bufferkstringmaxlength + **/ + static var kStringMaxLength(get, never):Int; + + private static inline function get_kStringMaxLength():Int { + return BufferModule.kStringMaxLength; + } + /** Re-encodes the given `Buffer` or `Uint8Array` instance from one character encoding to another. Returns a new `Buffer` instance. @@ -738,6 +736,16 @@ extern class Buffer extends Uint8Array { return BufferModule.btoa(data); } + /** + Resolves a `'blob:nodedata:...'` URL to the associated Blob. + // TODO(section-6): return typed Blob once web Blob externs are available. + + @see https://nodejs.org/api/buffer.html#bufferresolveobjecturlid + **/ + static inline function resolveObjectURL(id:String):Dynamic { + return BufferModule.resolveObjectURL(id); + } + /** `buffer.constants` is a property on the `buffer` module returned by `require('buffer')`, not on the `Buffer` global or a `Buffer` instance. @@ -787,11 +795,13 @@ private class Helper { private extern class BufferModule { static var INSPECT_MAX_BYTES:Int; static var kMaxLength(default, never):Int; + static var kStringMaxLength(default, never):Int; static function transcode(source:Uint8Array, fromEnc:String, toEnc:String):Buffer; static function isUtf8(input:EitherType):Bool; static function isAscii(input:EitherType):Bool; static function atob(data:String):String; static function btoa(data:String):String; + static function resolveObjectURL(id:String):Dynamic; static var constants(default, never):BufferConstants; } @@ -812,3 +822,11 @@ typedef BufferConstants = { **/ var MAX_STRING_LENGTH(default, never):Int; } + +/** + JSON representation produced by `Buffer.toJSON`. +**/ +typedef BufferJson = { + type:String, + data:Array +} diff --git a/src/js/node/events/EventEmitter.hx b/src/js/node/events/EventEmitter.hx index 786a11cd..109a5639 100644 --- a/src/js/node/events/EventEmitter.hx +++ b/src/js/node/events/EventEmitter.hx @@ -23,11 +23,9 @@ package js.node.events; import haxe.Constraints.Function; -import haxe.extern.Rest; -#if haxe4 import haxe.extern.EitherType; +import haxe.extern.Rest; import js.lib.Symbol; -#end /** Enumeration of events emitted by all `EventEmitter` instances. @@ -39,22 +37,14 @@ enum abstract EventEmitterEvent(Event) to Event { @see https://nodejs.org/api/events.html#events_event_newlistener **/ - #if haxe4 var NewListener:EventEmitterEvent<(eventName:EitherType, listener:Function) -> Void> = "newListener"; - #else - var NewListener:EventEmitterEventFunction->Void> = "newListener"; - #end /** The `'removeListener'` event is emitted after the `listener` is removed. @see https://nodejs.org/api/events.html#events_event_removelistener **/ - #if haxe4 var RemoveListener:EventEmitterEvent<(eventName:EitherType, listener:Function) -> Void> = "removeListener"; - #else - var RemoveListener:EventEmitterEventFunction->Void> = "removeListener"; - #end } /** @@ -64,7 +54,7 @@ enum abstract EventEmitterEvent(Event) to Event { **/ @:jsRequire("events", "EventEmitter") extern class EventEmitter> implements IEventEmitter { - function new(); + function new(?options:EventEmitterOptions); /** By default, a maximum of `10` listeners can be registered for any single @@ -85,22 +75,21 @@ extern class EventEmitter> implements IEventEmitter { @see https://nodejs.org/api/events.html#eventserrormonitor **/ - #if haxe4 static final errorMonitor:Symbol; - #else - static var errorMonitor(default, never):Dynamic; - #end /** Value: `Symbol.for('nodejs.rejection')` @see https://nodejs.org/api/events.html#eventscapturerejectionsymbol **/ - #if haxe4 static final captureRejectionSymbol:Symbol; - #else - static var captureRejectionSymbol(default, never):Dynamic; - #end + + /** + Change the default `captureRejections` option on all new `EventEmitter` objects. + + @see https://nodejs.org/api/events.html#eventscapturerejections + **/ + static var captureRejections:Bool; /** Returns a copy of the array of listeners for the event named `name`. @@ -154,11 +143,7 @@ extern class EventEmitter> implements IEventEmitter { @see https://nodejs.org/api/events.html#events_emitter_eventnames **/ - #if haxe4 function eventNames():Array>; - #else - function eventNames():Array; - #end /** Returns the current max listener value for the `EventEmitter` which is either @@ -170,10 +155,13 @@ extern class EventEmitter> implements IEventEmitter { function getMaxListeners():Int; /** - Returns the number of listeners listening to the event named `eventName`. + Returns the number of listeners listening for the event named `eventName`. + If `listener` is provided, it will return how many times the listener is + found in the list of the listeners of the event. @see https://nodejs.org/api/events.html#events_emitter_listenercount_eventname **/ + @:overload(function(eventName:Event, listener:T):Int {}) function listenerCount(eventName:Event):Int; /** @@ -265,6 +253,74 @@ extern class EventEmitter> implements IEventEmitter { function rawListeners(eventName:Event):Array; } +/** + `EventEmitter` constructor options. +**/ +typedef EventEmitterOptions = { + /** + Enables automatic capturing of promise rejection. + **/ + @:optional var captureRejections:Bool; +} + +/** + Integrates `EventEmitter` with `AsyncResource` for `EventEmitter`s that + require manual async tracking. + + @see https://nodejs.org/api/events.html#class-eventemitterasyncresource +**/ +@:jsRequire("events", "EventEmitterAsyncResource") +extern class EventEmitterAsyncResource extends EventEmitter { + function new(?options:EventEmitterAsyncResourceOptions); + + /** + Call all `destroy` hooks. This should only ever be called once. An error will + be thrown if it is called more than once. This must be manually called. If + the resource is left to be collected by the GC then the `destroy` hooks will + never be called. + **/ + function emitDestroy():Void; + + /** + The unique `asyncId` assigned to the resource. + **/ + var asyncId(default, null):Float; + + /** + The same `triggerAsyncId` that is passed to the `AsyncResource` constructor. + **/ + var triggerAsyncId(default, null):Float; + + /** + The underlying `AsyncResource`. + // TODO(section-7): type as async_hooks.AsyncResource once that package is externed. + **/ + var asyncResource(default, null):Dynamic; +} + +/** + Options for `EventEmitterAsyncResource`. +**/ +typedef EventEmitterAsyncResourceOptions = { + > EventEmitterOptions, + + /** + The type of async event. Default: `new.target.name` if instantiated using `new`, else `'EventEmitterAsyncResource'`. + **/ + @:optional var name:String; + + /** + The ID of the execution context that created this async event. Default: `executionAsyncId()`. + **/ + @:optional var triggerAsyncId:Float; + + /** + Disables automatic `emitDestroy` when the object is garbage collected. + Default: `false`. + **/ + @:optional var requireManualDestroy:Bool; +} + /** `IEventEmitter` interface is used as "any EventEmitter". @@ -276,11 +332,7 @@ extern interface IEventEmitter { function emit(eventName:Event, args:Rest):Bool; - #if haxe4 function eventNames():Array>; - #else - function eventNames():Array; - #end function getMaxListeners():Int; @@ -311,8 +363,4 @@ extern interface IEventEmitter { Abstract type for events. Its type parameter is a signature of a listener for a concrete event. **/ -#if haxe4 abstract Event(Dynamic) from String to String from Symbol to Symbol {} -#else -abstract Event(Dynamic) from String to String {} -#end diff --git a/src/js/node/process/ProcessFinalization.hx b/src/js/node/process/ProcessFinalization.hx new file mode 100644 index 00000000..458fa4c7 --- /dev/null +++ b/src/js/node/process/ProcessFinalization.hx @@ -0,0 +1,45 @@ +/* + * Copyright (C)2014-2020 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.node.process; + +/** + Process finalization registry API (`process.finalization`). + + @see https://nodejs.org/api/process.html#processfinalization +**/ +extern class ProcessFinalization { + /** + Registers a callback invoked before the event loop exits when `ref` becomes unreachable. + **/ + function register(ref:T, callback:(ref:T, event:String) -> Void):Void; + + /** + Registers a callback invoked on the `beforeExit` event when `ref` remains alive. + **/ + function registerBeforeExit(ref:T, callback:(ref:T, event:String) -> Void):Void; + + /** + Unregisters a resource previously registered with `register` / `registerBeforeExit`. + **/ + function unregister(ref:Dynamic):Void; +} diff --git a/src/js/node/process/ProcessPermission.hx b/src/js/node/process/ProcessPermission.hx new file mode 100644 index 00000000..1307a76e --- /dev/null +++ b/src/js/node/process/ProcessPermission.hx @@ -0,0 +1,35 @@ +/* + * Copyright (C)2014-2020 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package js.node.process; + +/** + Process permission model API (`process.permission`). + + @see https://nodejs.org/api/process.html#processpermission +**/ +extern class ProcessPermission { + /** + Verifies whether the process is able to access the given `scope` (with optional `reference`). + **/ + function has(scope:String, ?reference:String):Bool; +} diff --git a/src/js/node/stream/Duplex.hx b/src/js/node/stream/Duplex.hx index 47e4fe8e..7632f965 100644 --- a/src/js/node/stream/Duplex.hx +++ b/src/js/node/stream/Duplex.hx @@ -26,11 +26,7 @@ import haxe.extern.EitherType; import js.node.events.EventEmitter.Event; import js.node.stream.Readable.IReadable; import js.node.stream.Writable.IWritable; -#if haxe4 import js.lib.Error; -#else -import js.Error; -#end /** Writable streams are an abstraction for a destination to which data is written. @@ -303,6 +299,30 @@ extern class Duplex> extends Readable implements IDup // This field is defined in super class. // var isTTY(default, null):Bool; + + /** + A utility method for creating duplex streams from various sources. + // TODO(section-6): refine Blob / web stream input types once available. + + @see https://nodejs.org/api/stream.html#streamduplexfromsrc + **/ + static function from(src:Any):IDuplex; + + /** + Creates a Node.js `Duplex` from a pair of web streams. + // TODO(section-6): type web stream pair once available. + + @see https://nodejs.org/api/stream.html#streamduplexfromwebpair-options + **/ + static function fromWeb(pair:Any, ?options:DuplexNewOptions):IDuplex; + + /** + Creates a pair of web streams from a Node.js `Duplex`. + // TODO(section-6): return typed web stream pair once available. + + @see https://nodejs.org/api/stream.html#streamduplextowebstreamduplex-options + **/ + static function toWeb(streamDuplex:IDuplex):Any; } /** diff --git a/src/js/node/stream/Readable.hx b/src/js/node/stream/Readable.hx index b9a80091..259fdc29 100644 --- a/src/js/node/stream/Readable.hx +++ b/src/js/node/stream/Readable.hx @@ -26,11 +26,7 @@ import js.node.Iterator; import js.node.Stream; import js.node.events.EventEmitter.Event; import js.node.stream.Writable.IWritable; -#if haxe4 import js.lib.Error; -#else -import js.Error; -#end /** Readable streams are an abstraction for a source from which data is consumed. @@ -292,7 +288,23 @@ extern class Readable> extends Stream implements IR @see https://nodejs.org/api/stream.html#streamreadableisdisturbedstream **/ - static function isDisturbed(stream:Dynamic):Bool; + static function isDisturbed(stream:Any):Bool; + + /** + Creates a Node.js `Readable` from a web `ReadableStream`. + // TODO(section-6): type `readableStream` as web `ReadableStream` once available. + + @see https://nodejs.org/api/stream.html#streamreadablefromwebreadablestream-options + **/ + static function fromWeb(readableStream:Any, ?options:ReadableWebOptions):IReadable; + + /** + Creates a web `ReadableStream` from a Node.js `Readable`. + // TODO(section-6): return typed web `ReadableStream` once available. + + @see https://nodejs.org/api/stream.html#streamreadabletowebstreamreadable-options + **/ + static function toWeb(streamReadable:IReadable, ?options:ReadableToWebOptions):Any; } /** @@ -328,20 +340,12 @@ typedef ReadableNewOptions = { /** Implementation for the `stream._read()` method. **/ - #if haxe4 @:optional var read:(size:Int) -> Void; - #else - @:optional var read:Int->Void; - #end /** Implementation for the `stream._destroy()` method. **/ - #if haxe4 @:optional var destroy:(err:Null, callback:Null->Void) -> Void; - #else - @:optional var destroy:Null->(Null->Void)->Void; - #end /** Whether this stream should automatically call `.destroy()` on itself after ending. @@ -350,6 +354,27 @@ typedef ReadableNewOptions = { @:optional var autoDestroy:Bool; } +/** + Options for `Readable.fromWeb`. +**/ +typedef ReadableWebOptions = { + @:optional var encoding:String; + @:optional var highWaterMark:Int; + @:optional var objectMode:Bool; + @:optional var signal:js.node.web.AbortSignal; +} + +/** + Options for `Readable.toWeb`. +**/ +typedef ReadableToWebOptions = { + @:optional var strategy:{?highWaterMark:Int, ?size:Any->Int}; + /** + When `'bytes'`, produces a BYOB-capable bytes stream. + **/ + @:optional var type:String; +} + /** `IReadable` interface is used as "any Readable". diff --git a/src/js/node/stream/Transform.hx b/src/js/node/stream/Transform.hx index 8a713044..e5161d17 100644 --- a/src/js/node/stream/Transform.hx +++ b/src/js/node/stream/Transform.hx @@ -22,11 +22,7 @@ package js.node.stream; -#if haxe4 import js.lib.Error; -#else -import js.Error; -#end /** A `Transform` stream is a `Duplex` stream where the output is computed in some way from the input. @@ -52,11 +48,7 @@ extern class Transform> extends Duplex implements @see https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback **/ - #if haxe4 private function _transform(chunk:Dynamic, encoding:String, callback:(error:Null, data:Dynamic) -> Void):Void; - #else - private function _transform(chunk:Dynamic, encoding:String, callback:Null->Dynamic->Void):Void; - #end } /** @@ -68,11 +60,7 @@ typedef TransformNewOptions = { /** Implementation for the `stream._transform()` method. **/ - #if haxe4 @:optional var transform:(chunk:Dynamic, encoding:String, callback:(error:Null, data:Dynamic) -> Void) -> Void; - #else - @:optional var transform:Dynamic->String->(Null->Dynamic->Void)->Void; - #end /** Implementation for the `stream._flush()` method. diff --git a/src/js/node/stream/Writable.hx b/src/js/node/stream/Writable.hx index f4904c4f..dc531f51 100644 --- a/src/js/node/stream/Writable.hx +++ b/src/js/node/stream/Writable.hx @@ -26,14 +26,9 @@ import haxe.extern.EitherType; import js.node.Stream; import js.node.events.EventEmitter.Event; import js.node.stream.Readable.IReadable; -#if haxe4 import js.lib.Error; import js.lib.Object; import js.lib.Uint8Array; -#else -import js.Error; -import js.html.Uint8Array; -#end /** Writable streams are an abstraction for a destination to which data is written. @@ -258,6 +253,22 @@ extern class Writable> extends Stream implements IW @see https://nodejs.org/api/tty.html#tty_writestream_istty **/ var isTTY(default, null):Bool; + + /** + Creates a Node.js `Writable` from a web `WritableStream`. + // TODO(section-6): type `writableStream` as web `WritableStream` once available. + + @see https://nodejs.org/api/stream.html#streamwritablefromwebwritablestream-options + **/ + static function fromWeb(writableStream:Any, ?options:WritableNewOptions):IWritable; + + /** + Creates a web `WritableStream` from a Node.js `Writable`. + // TODO(section-6): return typed web `WritableStream` once available. + + @see https://nodejs.org/api/stream.html#streamwritabletowebstreamwritable + **/ + static function toWeb(streamWritable:IWritable):Any; } /** @@ -298,40 +309,24 @@ typedef WritableNewOptions = { /** `write` Implementation for the stream._write() method. **/ - #if haxe4 @:optional var write:(chunk:Dynamic, encoding:String, callback:Null->Void) -> Void; - #else - @:optional var write:Dynamic->String->Null->Void->Void; - #end /** `writev` Implementation for the stream._writev() method. **/ - #if haxe4 @:optional var writev:(chunks:Array, callback:Null->Void) -> Void; - #else - @:optional var writev:Array->(Null->Void)->Void; - #end /** `destroy` Implementation for the stream._destroy() method. **/ - #if haxe4 @:optional var destroy:(error:Null, callback:Null->Void) -> Void; - #else - @:optional var destroy:Null->(Null->Void)->Void; - #end /** `final` Implementation for the stream._final() method. **/ // TODO @native in typedef cannot work now // @:native("final") - #if haxe4 @:optional var final_:(error:Null) -> Void; - #else - @:optional var final_:Null->Void; - #end /** `autoDestroy` Whether this stream should automatically call .destroy() on itself after ending. Default: false. @@ -344,11 +339,7 @@ abstract WritableNewOptionsAdapter(WritableNewOptions) { @:from public static function from(options:WritableNewOptions):WritableNewOptionsAdapter { if (!Reflect.hasField(options, "final")) { - #if haxe4 Object.defineProperty(options, "final", {get: function() return options.final_}); - #else - untyped __js__("Object.defineProperty({0}, {1}, {2})", options, "final", {get: function() return options.final_}); - #end } return cast options; }