From ca18ef068e5240734b92633ca1093c1d0967ddca Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Sat, 2 Dec 2023 18:59:48 -0800 Subject: [PATCH 01/12] Use `new.target` instead of `instanceof` --- src/js/node/crypto.js | 18 +++++++++--------- src/js/node/fs.js | 2 +- src/js/node/readline.js | 4 ++-- src/js/node/stream.js | 10 +++++----- src/js/node/tty.js | 4 ++-- src/js/node/zlib.js | 14 +++++++------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/js/node/crypto.js b/src/js/node/crypto.js index 9ce1bca1c83ac6..f644710d3759a1 100644 --- a/src/js/node/crypto.js +++ b/src/js/node/crypto.js @@ -7461,7 +7461,7 @@ var require__ = __commonJS({ BlockHash = common.BlockHash, sha1_K = [1518500249, 1859775393, 2400959708, 3395469782]; function SHA1() { - if (!(this instanceof SHA1)) return new SHA1(); + if (!new.target) return new SHA1(); BlockHash.$call(this), (this.h = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]), (this.W = new Array(80)); @@ -7526,7 +7526,7 @@ var require__2 = __commonJS({ 3329325298, ]; function SHA256() { - if (!(this instanceof SHA256)) return new SHA256(); + if (!new.target) return new SHA256(); BlockHash.$call(this), (this.h = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]), (this.k = sha256_K), @@ -7576,7 +7576,7 @@ var require__3 = __commonJS({ var utils = require_utils4(), SHA256 = require__2(); function SHA224() { - if (!(this instanceof SHA224)) return new SHA224(); + if (!new.target) return new SHA224(); SHA256.$call(this), (this.h = [3238371032, 914150663, 812702999, 4144912697, 4290775857, 1750603025, 1694076839, 3204075428]); } @@ -7632,7 +7632,7 @@ var require__4 = __commonJS({ 3409855158, 1501505948, 4234509866, 1607167915, 987167468, 1816402316, 1246189591, ]; function SHA512() { - if (!(this instanceof SHA512)) return new SHA512(); + if (!new.target) return new SHA512(); BlockHash.$call(this), (this.h = [ 1779033703, 4089235720, 3144134277, 2227873595, 1013904242, 4271175723, 2773480762, 1595750129, 1359893119, @@ -7812,7 +7812,7 @@ var require__5 = __commonJS({ var utils = require_utils4(), SHA512 = require__4(); function SHA384() { - if (!(this instanceof SHA384)) return new SHA384(); + if (!new.target) return new SHA384(); SHA512.$call(this), (this.h = [ 3418070365, 3238371032, 1654270250, 914150663, 2438529370, 812702999, 355462360, 4144912697, 1731405415, @@ -7855,7 +7855,7 @@ var require_ripemd = __commonJS({ sum32_4 = utils.sum32_4, BlockHash = common.BlockHash; function RIPEMD160() { - if (!(this instanceof RIPEMD160)) return new RIPEMD160(); + if (!new.target) return new RIPEMD160(); BlockHash.$call(this), (this.h = [1732584193, 4023233417, 2562383102, 271733878, 3285377520]), (this.endian = "little"); @@ -7954,7 +7954,7 @@ var require_hmac = __commonJS({ function Hmac(hash, key, enc) { key = exportIfKeyObject(key); - if (!(this instanceof Hmac)) return new Hmac(hash, key, enc); + if (!new.target) return new Hmac(hash, key, enc); (this.Hash = hash), (this.blockSize = hash.blockSize / 8), (this.outSize = hash.outSize / 8), @@ -8965,7 +8965,7 @@ var require_hmac_drbg = __commonJS({ utils = require_utils2(), assert = require_minimalistic_assert(); function HmacDRBG(options) { - if (!(this instanceof HmacDRBG)) return new HmacDRBG(options); + if (!new.target) return new HmacDRBG(options); (this.hash = options.hash), (this.predResist = !!options.predResist), (this.outLen = this.hash.outSize), @@ -9196,7 +9196,7 @@ var require_ec = __commonJS({ KeyPair = require_key(), Signature = require_signature(); function EC(options) { - if (!(this instanceof EC)) return new EC(options); + if (!new.target) return new EC(options); typeof options == "string" && (assert(Object.prototype.hasOwnProperty.$call(curves, options), "Unknown curve " + options), (options = curves[options])), diff --git a/src/js/node/fs.js b/src/js/node/fs.js index 963afb11eff73f..cfdfa1a9f236ba 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -851,7 +851,7 @@ var defaultWriteStreamOptions = { }; var WriteStreamClass = (WriteStream = function WriteStream(path, options = defaultWriteStreamOptions) { - if (!(this instanceof WriteStream)) { + if (!new.target) { return new WriteStream(path, options); } diff --git a/src/js/node/readline.js b/src/js/node/readline.js index 16f4e199575069..efd5fed23b0151 100644 --- a/src/js/node/readline.js +++ b/src/js/node/readline.js @@ -1411,7 +1411,7 @@ function onResize() { } function InterfaceConstructor(input, output, completer, terminal) { - if (!(this instanceof InterfaceConstructor)) { + if (!new.target) { return new InterfaceConstructor(input, output, completer, terminal); } @@ -2536,7 +2536,7 @@ var _Interface = class Interface extends InterfaceConstructor { }; function Interface(input, output, completer, terminal) { - if (!(this instanceof Interface)) { + if (!new.target) { return new Interface(input, output, completer, terminal); } diff --git a/src/js/node/stream.js b/src/js/node/stream.js index 5297c033c59834..27941a7ae195c1 100644 --- a/src/js/node/stream.js +++ b/src/js/node/stream.js @@ -2000,7 +2000,7 @@ var require_legacy = __commonJS({ var { ArrayIsArray, ObjectSetPrototypeOf } = require_primordials(); function Stream(options) { - if (!(this instanceof Stream)) return new Stream(options); + if (!new.target) return new Stream(options); EE.$call(this, options); } Stream.prototype = {}; @@ -2264,7 +2264,7 @@ var require_readable = __commonJS({ var { Stream, prependListener } = require_legacy(); function Readable(options) { - if (!(this instanceof Readable)) return new Readable(options); + if (!new.target) return new Readable(options); const isDuplex = this instanceof require_duplex(); this._readableState = new ReadableState(options, this, isDuplex); if (options) { @@ -4386,7 +4386,7 @@ var require_duplex = __commonJS({ var Readable = require_readable(); function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); + if (!new.target) return new Duplex(options); Readable.$call(this, options); Writable.$call(this, options); @@ -4472,7 +4472,7 @@ var require_transform = __commonJS({ var { ERR_METHOD_NOT_IMPLEMENTED } = require_errors().codes; var Duplex = require_duplex(); function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); + if (!new.target) return new Transform(options); Duplex.$call(this, options); this._readableState.sync = false; @@ -4569,7 +4569,7 @@ var require_passthrough = __commonJS({ var Transform = require_transform(); function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); + if (!new.target) return new PassThrough(options); Transform.$call(this, options); } PassThrough.prototype = {}; diff --git a/src/js/node/tty.js b/src/js/node/tty.js index 6e138b0cfbaa30..0daba7b3cad6ff 100644 --- a/src/js/node/tty.js +++ b/src/js/node/tty.js @@ -4,7 +4,7 @@ const { ttySetMode, isatty, getWindowSize: _getWindowSize } = $lazy("tty"); const NumberIsInteger = Number.isInteger; function ReadStream(fd) { - if (!(this instanceof ReadStream)) return new ReadStream(fd); + if (!new.target) return new ReadStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").ReadStream.$call(this, "", { @@ -99,7 +99,7 @@ function warnOnDeactivatedColors(env) { } function WriteStream(fd) { - if (!(this instanceof WriteStream)) return new WriteStream(fd); + if (!new.target) return new WriteStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").WriteStream.$call(this, "", { diff --git a/src/js/node/zlib.js b/src/js/node/zlib.js index e2c4329688fae8..34d195dc48abd2 100644 --- a/src/js/node/zlib.js +++ b/src/js/node/zlib.js @@ -4123,31 +4123,31 @@ var require_lib = __commonJS({ return engine._processChunk(buffer, flushFlag); } function Deflate(opts) { - if (!(this instanceof Deflate)) return new Deflate(opts); + if (!new.target) return new Deflate(opts); Zlib.$call(this, opts, binding.DEFLATE); } function Inflate(opts) { - if (!(this instanceof Inflate)) return new Inflate(opts); + if (!new.target) return new Inflate(opts); Zlib.$call(this, opts, binding.INFLATE); } function Gzip(opts) { - if (!(this instanceof Gzip)) return new Gzip(opts); + if (!new.target) return new Gzip(opts); Zlib.$call(this, opts, binding.GZIP); } function Gunzip(opts) { - if (!(this instanceof Gunzip)) return new Gunzip(opts); + if (!new.target) return new Gunzip(opts); Zlib.$call(this, opts, binding.GUNZIP); } function DeflateRaw(opts) { - if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts); + if (!new.target) return new DeflateRaw(opts); Zlib.$call(this, opts, binding.DEFLATERAW); } function InflateRaw(opts) { - if (!(this instanceof InflateRaw)) return new InflateRaw(opts); + if (!new.target) return new InflateRaw(opts); Zlib.$call(this, opts, binding.INFLATERAW); } function Unzip(opts) { - if (!(this instanceof Unzip)) return new Unzip(opts); + if (!new.target) return new Unzip(opts); Zlib.$call(this, opts, binding.UNZIP); } function isValidFlushFlag(flag) { From 367cccc35ca919a60d3405573a546890c72cf364 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Sat, 2 Dec 2023 23:58:32 -0800 Subject: [PATCH 02/12] Fix bug with syntax highlighter --- src/bun.zig | 60 +++++++++++++++++++++------- test/js/bun/util/highlighter.test.ts | 6 ++- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/bun.zig b/src/bun.zig index e92ee09928cf30..c2bcb4893ec1c4 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -277,7 +277,7 @@ pub const fmt = struct { var remain = text; var prev_keyword: ?Keyword = null; - while (remain.len > 0) { + outer: while (remain.len > 0) { if (js_lexer.isIdentifierStart(remain[0])) { var i: usize = 1; @@ -351,24 +351,56 @@ pub const fmt = struct { prev_keyword = null; var i: usize = 1; - for (remain[i..]) |c| { - if (c == char) { - if (i < remain.len) { - i += 1; + while (i < remain.len and remain[i] != char) { + if (comptime char == '`') { + if (remain[i] == '$' and i + 1 < remain.len and remain[i + 1] == '{') { + const curly_start = i; + i += 2; + + while (i < remain.len and remain[i] != '}') { + if (remain[i] == '\\') { + i += 1; + } + i += 1; + } + + try writer.print(Output.prettyFmt("{s}", true), .{remain[0..curly_start]}); + try writer.writeAll("${"); + const curly_remain = QuickAndDirtyJavaScriptSyntaxHighlighter{ + .text = remain[curly_start + 2 .. i], + .enable_colors = this.enable_colors, + .limited = false, + }; + + if (curly_remain.text.len > 0) { + try curly_remain.format("", .{}, writer); + } + + if (i < remain.len and remain[i] == '}') { + i += 1; + } + try writer.writeAll("}"); + remain = remain[i..]; + i = 0; + if (remain.len > 0 and remain[0] == char) { + try writer.writeAll(Output.prettyFmt("`", true)); + remain = remain[1..]; + continue :outer; + } + continue; } - break; - } else if (c == '\\') { + } + + if (i + 1 < remain.len and remain[i] == '\\') { i += 1; - if (i < remain.len) { - i += 1; - } - } else { - if (i < remain.len) { - i += 1; - } } + + i += 1; } + // Include the trailing quote, if any + i += @as(usize, @intFromBool(i > 1 and i < remain.len and remain[i] == char)); + try writer.print(Output.prettyFmt("{s}", true), .{remain[0..i]}); remain = remain[i..]; }, diff --git a/test/js/bun/util/highlighter.test.ts b/test/js/bun/util/highlighter.test.ts index 91ef6768b505d0..af3b7abb2f5a6b 100644 --- a/test/js/bun/util/highlighter.test.ts +++ b/test/js/bun/util/highlighter.test.ts @@ -3,5 +3,7 @@ import { readFileSync, writeFileSync } from "fs"; // @ts-expect-error const highlighter: (code: string) => string = globalThis[Symbol.for("Bun.lazy")]("unstable_syntaxHighlight"); -// TODO: write tests for syntax highlighting -test("highlighter", () => {}); +test("highlighter", () => { + expect(highlighter("`can do ${123} ${'123'} ${`123`}`").length).toBeLessThan(150); + expect(highlighter("`can do ${123} ${'123'} ${`123`}`123").length).toBeLessThan(150); +}); From 88c1e4df72030fdef006f3a826ec87c7461a05f6 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 03:36:25 -0800 Subject: [PATCH 03/12] Disable for streams --- src/js/node/stream.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/node/stream.js b/src/js/node/stream.js index 27941a7ae195c1..a9b87fec1d37d9 100644 --- a/src/js/node/stream.js +++ b/src/js/node/stream.js @@ -4386,7 +4386,7 @@ var require_duplex = __commonJS({ var Readable = require_readable(); function Duplex(options) { - if (!new.target) return new Duplex(options); + if (!(this instanceof Duplex)) return new Duplex(options); Readable.$call(this, options); Writable.$call(this, options); @@ -4472,7 +4472,7 @@ var require_transform = __commonJS({ var { ERR_METHOD_NOT_IMPLEMENTED } = require_errors().codes; var Duplex = require_duplex(); function Transform(options) { - if (!new.target) return new Transform(options); + if (!(this instanceof Transform)) return new Transform(options); Duplex.$call(this, options); this._readableState.sync = false; @@ -4569,7 +4569,7 @@ var require_passthrough = __commonJS({ var Transform = require_transform(); function PassThrough(options) { - if (!new.target) return new PassThrough(options); + if (!(this instanceof PassThrough)) return new PassThrough(options); Transform.$call(this, options); } PassThrough.prototype = {}; From 5535a5ce7610651b2c0f9eec8cdb74cc69e35135 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:41:21 -0800 Subject: [PATCH 04/12] Faster napi --- src/bun.js/bindings/ZigGlobalObject.cpp | 20 +++- src/bun.js/bindings/ZigGlobalObject.h | 5 + src/bun.js/bindings/napi.cpp | 153 ++++++++++++++++++++---- src/bun.js/bindings/napi.h | 8 +- src/bun.js/bindings/napi_external.cpp | 2 +- src/bun.js/bindings/napi_external.h | 32 ++++- src/napi/napi.zig | 2 +- 7 files changed, 186 insertions(+), 36 deletions(-) diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 511d7ea6a81f13..5b8a5fae07960f 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -137,7 +137,7 @@ #include "BunObject.h" #include "JSNextTickQueue.h" #include "NodeHTTP.h" - +#include "napi_external.h" using namespace Bun; extern "C" JSC__JSValue Bun__NodeUtil__jsParseArgs(JSC::JSGlobalObject*, JSC::CallFrame*); @@ -3061,6 +3061,22 @@ void GlobalObject::finishCreation(VM& vm) this->initGeneratedLazyClasses(); + m_NapiExternalStructure.initLater( + [](const JSC::LazyProperty::Initializer& init) { + auto& global = *reinterpret_cast(init.owner); + + init.set( + Bun::NapiExternal::createStructure(init.vm, init.owner, init.owner->objectPrototype())); + }); + + m_NapiPrototypeStructure.initLater( + [](const JSC::LazyProperty::Initializer& init) { + auto& global = *reinterpret_cast(init.owner); + + init.set( + Bun::NapiPrototype::createStructure(init.vm, init.owner, init.owner->objectPrototype())); + }); + m_cachedGlobalObjectStructure.initLater( [](const JSC::LazyProperty::Initializer& init) { auto& global = *reinterpret_cast(init.owner); @@ -3931,6 +3947,8 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSSocketAddressStructure.visit(visitor); thisObject->m_cachedGlobalObjectStructure.visit(visitor); thisObject->m_cachedGlobalProxyStructure.visit(visitor); + thisObject->m_NapiExternalStructure.visit(visitor); + thisObject->m_NapiPrototypeStructure.visit(visitor); thisObject->mockModule.mockFunctionStructure.visit(visitor); thisObject->mockModule.mockResultStructure.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 40004b9f8444a8..6c3b78920d17ab 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -258,6 +258,9 @@ class GlobalObject : public JSC::JSGlobalObject { JSWeakMap* vmModuleContextMap() { return m_vmModuleContextMap.getInitializedOnMainThread(this); } + Structure* NapiExternalStructure() { return m_NapiExternalStructure.getInitializedOnMainThread(this); } + Structure* NapiPrototypeStructure() { return m_NapiPrototypeStructure.getInitializedOnMainThread(this); } + bool hasProcessObject() const { return m_processObject.isInitialized(); } JSC::JSObject* processObject() { return m_processObject.getInitializedOnMainThread(this); } @@ -515,6 +518,8 @@ class GlobalObject : public JSC::JSGlobalObject { LazyProperty m_asyncBoundFunctionStructure; LazyProperty m_JSDOMFileConstructor; LazyProperty m_JSCryptoKey; + LazyProperty m_NapiExternalStructure; + LazyProperty m_NapiPrototypeStructure; LazyProperty m_bunObject; LazyProperty m_cryptoObject; diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 47353f331eb777..9e6f0c9e03f3ae 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -59,6 +59,26 @@ using namespace JSC; using namespace Zig; +#define NAPI_VERBOSE 0 + +#if !OS(WINDOWS) +#if NAPI_VERBOSE +#include + +#define NAPI_PREMABLE \ + printf("[napi] %s:%d:%s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); +#else + +#endif + +#ifndef NAPI_PREMABLE + +#define NAPI_PREMABLE + +#endif + +#endif + namespace Napi { JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSObject* object, JSC::JSGlobalObject* globalObject) @@ -161,17 +181,8 @@ void NapiRef::clear() // namespace Napi { // class Reference // } -#define StackAllocatedCallFramePointerTag 62 -typedef struct StackAllocatedCallFrame { - void* dataPtr; - JSC::EncodedJSValue thisValue; - // this is "bar" in: - // set foo(bar) - JSC::EncodedJSValue argument1; -} StackAllocatedCallFrame; - -extern "C" Zig::GlobalObject* -Bun__getDefaultGlobal(); + +extern "C" Zig::GlobalObject* Bun__getDefaultGlobal(); WTF_MAKE_ISO_ALLOCATED_IMPL(NapiRef); @@ -314,6 +325,8 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t extern "C" napi_status napi_set_property(napi_env env, napi_value target, napi_value key, napi_value value) { + NAPI_PREMABLE + if (UNLIKELY(!env || !target || !key)) { return napi_invalid_arg; } @@ -338,6 +351,8 @@ extern "C" napi_status napi_set_property(napi_env env, napi_value target, extern "C" napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool* result) { + NAPI_PREMABLE + if (UNLIKELY(!object || !env)) { return napi_invalid_arg; } @@ -360,6 +375,8 @@ extern "C" napi_status napi_has_property(napi_env env, napi_value object, extern "C" napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value* result) { + NAPI_PREMABLE + auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -382,6 +399,8 @@ extern "C" napi_status napi_get_property(napi_env env, napi_value object, extern "C" napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool* result) { + NAPI_PREMABLE + auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -401,6 +420,8 @@ extern "C" napi_status napi_delete_property(napi_env env, napi_value object, extern "C" napi_status napi_has_own_property(napi_env env, napi_value object, napi_value key, bool* result) { + NAPI_PREMABLE + auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -422,6 +443,8 @@ extern "C" napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, napi_value value) { + NAPI_PREMABLE + auto globalObject = toJS(env); auto target = toJS(object).getObject(); auto& vm = globalObject->vm(); @@ -452,6 +475,8 @@ extern "C" napi_status napi_create_arraybuffer(napi_env env, napi_value* result) { + NAPI_PREMABLE + JSC::JSGlobalObject* globalObject = toJS(env); if (UNLIKELY(!globalObject || !result)) { return napi_invalid_arg; @@ -491,6 +516,7 @@ extern "C" napi_status napi_has_named_property(napi_env env, napi_value object, const char* utf8name, bool* result) { + NAPI_PREMABLE auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -513,6 +539,7 @@ extern "C" napi_status napi_get_named_property(napi_env env, napi_value object, const char* utf8name, napi_value* result) { + NAPI_PREMABLE auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -671,6 +698,8 @@ extern "C" napi_status napi_wrap(napi_env env, napi_ref* result) { + NAPI_PREMABLE + JSValue value = toJS(js_object); if (!value || value.isUndefinedOrNull()) { return napi_object_expected; @@ -723,6 +752,8 @@ extern "C" napi_status napi_wrap(napi_env env, extern "C" napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result) { + NAPI_PREMABLE + JSValue value = toJS(js_object); if (!value || value.isUndefinedOrNull()) { return napi_object_expected; @@ -760,6 +791,8 @@ extern "C" napi_status napi_remove_wrap(napi_env env, napi_value js_object, extern "C" napi_status napi_unwrap(napi_env env, napi_value js_object, void** result) { + NAPI_PREMABLE + JSValue value = toJS(js_object); if (!value.isObject()) { @@ -787,6 +820,7 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name, size_t length, napi_callback cb, void* data, napi_value* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -831,6 +865,8 @@ extern "C" napi_status napi_get_cb_info( napi_value* this_arg, // [out] Receives the JS 'this' arg for the call void** data) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); auto inputArgsCount = argc == nullptr ? 0 : *argc; JSC::CallFrame* callFrame = reinterpret_cast(cbinfo); @@ -936,6 +972,7 @@ extern "C" napi_status napi_throw_error(napi_env env, const char* code, const char* msg) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -951,7 +988,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result) { - + NAPI_PREMABLE JSC::JSValue val = toJS(value); if (!val || !val.isObject()) { @@ -991,7 +1028,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, extern "C" void napi_set_ref(NapiRef* ref, JSC__JSValue val_) { - + NAPI_PREMABLE JSC::JSValue val = JSC::JSValue::decode(val_); if (val) { ref->strongRef.set(ref->globalObject->vm(), val); @@ -1006,6 +1043,7 @@ extern "C" napi_status napi_add_finalizer(napi_env env, napi_value js_object, void* finalize_hint, napi_ref* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1025,6 +1063,7 @@ extern "C" napi_status napi_add_finalizer(napi_env env, napi_value js_object, extern "C" napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { + NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->unref(); *result = napiRef->refCount; @@ -1037,6 +1076,7 @@ extern "C" napi_status napi_reference_unref(napi_env env, napi_ref ref, extern "C" napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result) { + NAPI_PREMABLE NapiRef* napiRef = toJS(ref); *result = toNapi(napiRef->value()); @@ -1045,12 +1085,14 @@ extern "C" napi_status napi_get_reference_value(napi_env env, napi_ref ref, extern "C" JSC__JSValue napi_get_reference_value_internal(NapiRef* napiRef) { + NAPI_PREMABLE return JSC::JSValue::encode(napiRef->value()); } extern "C" napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { + NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->ref(); *result = napiRef->refCount; @@ -1059,6 +1101,7 @@ extern "C" napi_status napi_reference_ref(napi_env env, napi_ref ref, extern "C" napi_status napi_delete_reference(napi_env env, napi_ref ref) { + NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->~NapiRef(); return napi_ok; @@ -1066,6 +1109,7 @@ extern "C" napi_status napi_delete_reference(napi_env env, napi_ref ref) extern "C" void napi_delete_reference_internal(napi_ref ref) { + NAPI_PREMABLE NapiRef* napiRef = toJS(ref); delete napiRef; } @@ -1074,6 +1118,7 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1091,6 +1136,7 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env, extern "C" napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1114,6 +1160,7 @@ extern "C" napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t* adjusted_value) { + NAPI_PREMABLE if (change_in_bytes > 0) { toJS(env)->vm().heap.deprecatedReportExtraMemory(change_in_bytes); } @@ -1123,6 +1170,7 @@ extern "C" napi_status napi_adjust_external_memory(napi_env env, extern "C" napi_status napi_is_exception_pending(napi_env env, bool* result) { + NAPI_PREMABLE auto globalObject = toJS(env); *result = globalObject->vm().exceptionForInspection() != nullptr; return napi_ok; @@ -1130,6 +1178,7 @@ extern "C" napi_status napi_is_exception_pending(napi_env env, bool* result) extern "C" napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result) { + NAPI_PREMABLE auto globalObject = toJS(env); *result = toNapi(JSC::JSValue(globalObject->vm().lastException())); globalObject->vm().clearLastException(); @@ -1139,6 +1188,7 @@ extern "C" napi_status napi_get_and_clear_last_exception(napi_env env, extern "C" napi_status napi_fatal_exception(napi_env env, napi_value err) { + NAPI_PREMABLE auto globalObject = toJS(env); JSC::JSValue value = toJS(err); JSC::JSObject* obj = value.getObject(); @@ -1153,6 +1203,7 @@ extern "C" napi_status napi_fatal_exception(napi_env env, extern "C" napi_status napi_throw(napi_env env, napi_value error) { + NAPI_PREMABLE auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1171,6 +1222,7 @@ extern "C" napi_status node_api_symbol_for(napi_env env, const char* utf8description, size_t length, napi_value* result) { + NAPI_PREMABLE auto* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); if (UNLIKELY(!result || !utf8description)) { @@ -1188,6 +1240,7 @@ extern "C" napi_status node_api_create_syntax_error(napi_env env, napi_value msg, napi_value* result) { + NAPI_PREMABLE if (UNLIKELY(!result)) { return napi_invalid_arg; } @@ -1209,6 +1262,8 @@ extern "C" napi_status node_api_throw_syntax_error(napi_env env, const char* code, const char* msg) { + NAPI_PREMABLE + auto message = msg ? WTF::String::fromUTF8(msg) : String(); auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1225,6 +1280,7 @@ extern "C" napi_status node_api_throw_syntax_error(napi_env env, extern "C" napi_status napi_throw_type_error(napi_env env, const char* code, const char* msg) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1259,6 +1315,7 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1266,6 +1323,10 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, JSC::JSValue messageValue = toJS(msg); WTF::String message = messageValue.toWTFString(globalObject); + if (message.isEmpty()) { + message = "Error"_s; + } + auto* error = JSC::createError(globalObject, message); if (codeValue) { error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); @@ -1277,6 +1338,7 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, extern "C" napi_status napi_throw_range_error(napi_env env, const char* code, const char* msg) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1290,6 +1352,7 @@ extern "C" napi_status napi_throw_range_error(napi_env env, const char* code, extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1310,6 +1373,7 @@ extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value) } extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1331,6 +1395,8 @@ extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value) extern "C" napi_status napi_get_global(napi_env env, napi_value* result) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); *result = reinterpret_cast(globalObject->globalThis()); @@ -1341,6 +1407,7 @@ extern "C" napi_status napi_create_range_error(napi_env env, napi_value code, napi_value msg, napi_value* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1359,6 +1426,7 @@ extern "C" napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); // handle: @@ -1379,6 +1447,7 @@ extern "C" napi_status napi_create_dataview(napi_env env, size_t length, size_t byte_offset, napi_value* result) { + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1541,7 +1610,7 @@ void NapiClass::finishCreation(VM& vm, NativeExecutable* executable, unsigned le prototypePropertyCount += property.attributes & napi_static ? 0 : 1; } - NapiPrototype* prototype = NapiPrototype::create(vm, globalObject); + NapiPrototype* prototype = NapiPrototype::create(vm, globalObject->NapiPrototypeStructure()); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1599,6 +1668,7 @@ static napi_extended_error_info last_error_info; extern "C" napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info** result) { + NAPI_PREMABLE auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto lastException = vm.lastException(); @@ -1633,6 +1703,8 @@ extern "C" napi_status napi_define_class(napi_env env, const napi_property_descriptor* properties, napi_value* result) { + NAPI_PREMABLE + if (utf8name == nullptr) { return napi_invalid_arg; } @@ -1657,6 +1729,7 @@ extern "C" napi_status napi_define_class(napi_env env, extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result) { + NAPI_PREMABLE if (UNLIKELY(result == nullptr || value == nullptr || env == nullptr)) { return napi_invalid_arg; } @@ -1684,7 +1757,7 @@ extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value, extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) { - + NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1714,6 +1787,8 @@ extern "C" napi_status napi_create_external_buffer(napi_env env, size_t length, void* finalize_hint, napi_value* result) { + + NAPI_PREMABLE if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1737,6 +1812,8 @@ extern "C" napi_status napi_create_external_buffer(napi_env env, size_t length, extern "C" napi_status napi_create_external_arraybuffer(napi_env env, void* external_data, size_t byte_length, napi_finalize finalize_cb, void* finalize_hint, napi_value* result) { + NAPI_PREMABLE + if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1762,6 +1839,8 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, size_t bufsize, size_t* writtenPtr) { + NAPI_PREMABLE + JSGlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1823,6 +1902,8 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, uint32_t index, napi_value* result) { + NAPI_PREMABLE + JSValue jsValue = toJS(objectValue); if (UNLIKELY(!env || !jsValue || !jsValue.isObject())) { return napi_invalid_arg; @@ -1844,6 +1925,8 @@ extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, extern "C" napi_status napi_create_object(napi_env env, napi_value* result) { + NAPI_PREMABLE + if (UNLIKELY(result == nullptr || env == nullptr)) { return napi_invalid_arg; } @@ -1851,7 +1934,7 @@ extern "C" napi_status napi_create_object(napi_env env, napi_value* result) Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - JSValue value = JSValue(NapiPrototype::create(vm, globalObject)); + JSValue value = JSValue(NapiPrototype::create(vm, globalObject->NapiPrototypeStructure())); *result = toNapi(value); JSC::EnsureStillAliveScope ensureStillAlive(value); @@ -1863,6 +1946,7 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, void* finalize_hint, napi_value* result) { + NAPI_PREMABLE if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1870,9 +1954,9 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - auto* structure = Bun::NapiExternal::createStructure(vm, globalObject, globalObject->objectPrototype()); - JSValue value = JSValue(Bun::NapiExternal::create(vm, structure, data, finalize_hint, finalize_cb)); - + auto* structure = globalObject->NapiExternalStructure(); + JSValue value = Bun::NapiExternal::create(vm, structure, data, finalize_hint, reinterpret_cast(finalize_cb)); + JSC::EnsureStillAliveScope ensureStillAlive(value); *result = toNapi(value); return napi_ok; } @@ -1880,6 +1964,8 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, extern "C" napi_status napi_typeof(napi_env env, napi_value val, napi_valuetype* result) { + NAPI_PREMABLE + if (UNLIKELY(result == nullptr)) return napi_invalid_arg; @@ -1940,6 +2026,8 @@ extern "C" napi_status napi_typeof(napi_env env, napi_value val, *result = napi_object; return napi_ok; } + + break; } } } @@ -1973,6 +2061,8 @@ extern "C" napi_status napi_get_value_bigint_words(napi_env env, size_t* word_count, uint64_t* words) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::JSValue jsValue = toJS(value); @@ -2012,6 +2102,8 @@ extern "C" napi_status napi_get_value_bigint_words(napi_env env, extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, void** result) { + NAPI_PREMABLE + if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -2029,6 +2121,8 @@ extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, extern "C" napi_status napi_get_instance_data(napi_env env, void** data) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); if (UNLIKELY(data == nullptr)) { return napi_invalid_arg; @@ -2043,6 +2137,8 @@ extern "C" napi_status napi_set_instance_data(napi_env env, napi_finalize finalize_cb, void* finalize_hint) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); if (data) globalObject->napiInstanceData = data; @@ -2059,6 +2155,8 @@ extern "C" napi_status napi_create_bigint_words(napi_env env, const uint64_t* words, napi_value* result) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto* bigint = JSC::JSBigInt::tryCreateWithLength(vm, word_count); @@ -2085,6 +2183,8 @@ extern "C" napi_status napi_create_bigint_words(napi_env env, extern "C" napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -2118,6 +2218,8 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, const napi_value* argv, napi_value* result_ptr) { + NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -2139,14 +2241,21 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, } JSC::JSValue thisValue = toJS(recv_napi); + auto scope = DECLARE_THROW_SCOPE(vm); if (thisValue.isEmpty()) { thisValue = JSC::jsUndefined(); } JSC::JSValue result = call(globalObject, funcValue, callData, thisValue, args); if (result_ptr) { - *result_ptr = toNapi(result); + if (result.isEmpty()) { + *result_ptr = toNapi(JSC::jsUndefined()); + } else { + *result_ptr = toNapi(result); + } } - return napi_ok; -} \ No newline at end of file + RETURN_IF_EXCEPTION(scope, napi_generic_failure); + + RELEASE_AND_RETURN(scope, napi_ok); +} diff --git a/src/bun.js/bindings/napi.h b/src/bun.js/bindings/napi.h index dfcdc8bf531526..da64bb72902659 100644 --- a/src/bun.js/bindings/napi.h +++ b/src/bun.js/bindings/napi.h @@ -192,19 +192,13 @@ class NapiPrototype : public JSC::JSDestructibleObject { DECLARE_INFO; - static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure) + static NapiPrototype* create(VM& vm, Structure* structure) { NapiPrototype* footprint = new (NotNull, allocateCell(vm)) NapiPrototype(vm, structure); footprint->finishCreation(vm); return footprint; } - static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject) - { - Structure* structure = createStructure(vm, globalObject, globalObject->objectPrototype()); - return create(vm, globalObject, structure); - } - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { ASSERT(globalObject); diff --git a/src/bun.js/bindings/napi_external.cpp b/src/bun.js/bindings/napi_external.cpp index 8b4798d6f328a0..bffa96cf6dcad3 100644 --- a/src/bun.js/bindings/napi_external.cpp +++ b/src/bun.js/bindings/napi_external.cpp @@ -6,7 +6,7 @@ namespace Bun { NapiExternal::~NapiExternal() { if (finalizer) { - finalizer(toNapi(globalObject()), m_value, m_finalizerHint); + reinterpret_cast(finalizer)(toNapi(globalObject()), m_value, m_finalizerHint); } } diff --git a/src/bun.js/bindings/napi_external.h b/src/bun.js/bindings/napi_external.h index 30924fa34799bb..c4826b3037a921 100644 --- a/src/bun.js/bindings/napi_external.h +++ b/src/bun.js/bindings/napi_external.h @@ -6,7 +6,6 @@ #include "BunBuiltinNames.h" #include "BunClientData.h" -#include "node_api.h" namespace Bun { @@ -48,14 +47,33 @@ class NapiExternal : public JSC::JSDestructibleObject { JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); } - static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure, void* value, void* finalizer_hint, napi_finalize finalizer) + static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure, void* value, void* finalizer_hint, void* finalizer) { NapiExternal* accessor = new (NotNull, JSC::allocateCell(vm)) NapiExternal(vm, structure); + accessor->finishCreation(vm, value, finalizer_hint, finalizer); + +#if BUN_DEBUG + if (auto* callFrame = vm.topCallFrame) { + auto origin = callFrame->callerSourceOrigin(vm); + accessor->sourceOriginURL = origin.string(); + + std::unique_ptr> stackTrace = makeUnique>(); + vm.interpreter.getStackTrace(accessor, *stackTrace, 0, 20); + if (!stackTrace->isEmpty()) { + for (auto& frame : *stackTrace) { + if (frame.hasLineAndColumnInfo()) { + frame.computeLineAndColumn(accessor->sourceOriginLine, accessor->sourceOriginColumn); + break; + } + } + } + } +#endif return accessor; } - void finishCreation(JSC::VM& vm, void* value, void* finalizer_hint, napi_finalize finalizer) + void finishCreation(JSC::VM& vm, void* value, void* finalizer_hint, void* finalizer) { Base::finishCreation(vm); m_value = value; @@ -69,7 +87,13 @@ class NapiExternal : public JSC::JSDestructibleObject { void* m_value; void* m_finalizerHint; - napi_finalize finalizer; + void* finalizer; + +#if BUN_DEBUG + String sourceOriginURL = String(); + unsigned sourceOriginLine = 0; + unsigned sourceOriginColumn = 0; +#endif }; } // namespace Zig \ No newline at end of file diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 082405a55c9f81..bebf050a9b6572 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -620,7 +620,7 @@ pub export fn napi_new_instance(env: napi_env, constructor: napi_value, argc: us pub export fn napi_instanceof(env: napi_env, object: napi_value, constructor: napi_value, result: *bool) napi_status { log("napi_instanceof", .{}); // TODO: does this throw object_expected in node? - result.* = object.isCell() and object.isInstanceOf(env, constructor); + result.* = object.isObject() and object.isInstanceOf(env, constructor); return .ok; } pub extern fn napi_get_cb_info(env: napi_env, cbinfo: napi_callback_info, argc: [*c]usize, argv: *napi_value, this_arg: *napi_value, data: [*]*anyopaque) napi_status; From 9e916bc2ccf739cba730700c99b7036b8a0b7d50 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:54:39 -0800 Subject: [PATCH 05/12] Align stream constructor more with node.js --- src/js/node/stream.js | 49 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/js/node/stream.js b/src/js/node/stream.js index a9b87fec1d37d9..b07f76d1194aa7 100644 --- a/src/js/node/stream.js +++ b/src/js/node/stream.js @@ -75,6 +75,7 @@ function ERR_INVALID_ARG_VALUE(name, value, reason) { return new Error(`The value '${value}' is invalid for argument '${name}'. Reason: ${reason}`); } +var isCallingDuplexStreamConstructor = false; // node_modules/readable-stream/lib/ours/primordials.js var require_primordials = __commonJS({ "node_modules/readable-stream/lib/ours/primordials.js"(exports, module) { @@ -2000,7 +2001,6 @@ var require_legacy = __commonJS({ var { ArrayIsArray, ObjectSetPrototypeOf } = require_primordials(); function Stream(options) { - if (!new.target) return new Stream(options); EE.$call(this, options); } Stream.prototype = {}; @@ -2264,23 +2264,43 @@ var require_readable = __commonJS({ var { Stream, prependListener } = require_legacy(); function Readable(options) { - if (!new.target) return new Readable(options); - const isDuplex = this instanceof require_duplex(); - this._readableState = new ReadableState(options, this, isDuplex); + if (!(this instanceof Readable)) return new Readable(options); + const wasCallingDuplexStreamConstructor = isCallingDuplexStreamConstructor; + isCallingDuplexStreamConstructor = false; + + this._events ??= { + close: undefined, + error: undefined, + data: undefined, + end: undefined, + readable: undefined, + // Skip uncommon events... + // pause: undefined, + // resume: undefined, + // pipe: undefined, + // unpipe: undefined, + // [destroyImpl.kConstruct]: undefined, + // [destroyImpl.kDestroy]: undefined, + }; + + this._readableState = new ReadableState(options, this, wasCallingDuplexStreamConstructor); + if (options) { const { read, destroy, construct, signal } = options; - if (typeof read === "function") this._read = read; - if (typeof destroy === "function") this._destroy = destroy; - if (typeof construct === "function") this._construct = construct; - if (signal && !isDuplex) addAbortSignal(signal, this); + if ($isCallable(read)) this._read = read; + if ($isCallable(destroy)) this._destroy = destroy; + if ($isCallable(construct)) this._construct = construct; + if (signal) addAbortSignal(signal, this); } Stream.$call(this, options); - destroyImpl.construct(this, () => { - if (this._readableState.needReadable) { - maybeReadMore(this, this._readableState); - } - }); + if (!$isUndefinedOrNull(this._construct)) { + destroyImpl.construct(this, () => { + if (this._readableState.needReadable) { + maybeReadMore(this, this._readableState); + } + }); + } } Readable.prototype = {}; ObjectSetPrototypeOf(Readable.prototype, Stream.prototype); @@ -4387,7 +4407,10 @@ var require_duplex = __commonJS({ function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); + const prevIsCallingDuplexStreamConstructor = isCallingDuplexStreamConstructor; + isCallingDuplexStreamConstructor = true; Readable.$call(this, options); + isCallingDuplexStreamConstructor = prevIsCallingDuplexStreamConstructor; Writable.$call(this, options); if (options) { From e1ff68cbface2547ba73e54da1768194c1d8af7a Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:55:00 -0800 Subject: [PATCH 06/12] Undo other new.target changes --- src/js/node/fs.js | 2 +- src/js/node/readline.js | 4 ++-- src/js/node/tty.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/js/node/fs.js b/src/js/node/fs.js index cfdfa1a9f236ba..963afb11eff73f 100644 --- a/src/js/node/fs.js +++ b/src/js/node/fs.js @@ -851,7 +851,7 @@ var defaultWriteStreamOptions = { }; var WriteStreamClass = (WriteStream = function WriteStream(path, options = defaultWriteStreamOptions) { - if (!new.target) { + if (!(this instanceof WriteStream)) { return new WriteStream(path, options); } diff --git a/src/js/node/readline.js b/src/js/node/readline.js index efd5fed23b0151..16f4e199575069 100644 --- a/src/js/node/readline.js +++ b/src/js/node/readline.js @@ -1411,7 +1411,7 @@ function onResize() { } function InterfaceConstructor(input, output, completer, terminal) { - if (!new.target) { + if (!(this instanceof InterfaceConstructor)) { return new InterfaceConstructor(input, output, completer, terminal); } @@ -2536,7 +2536,7 @@ var _Interface = class Interface extends InterfaceConstructor { }; function Interface(input, output, completer, terminal) { - if (!new.target) { + if (!(this instanceof Interface)) { return new Interface(input, output, completer, terminal); } diff --git a/src/js/node/tty.js b/src/js/node/tty.js index 0daba7b3cad6ff..6e138b0cfbaa30 100644 --- a/src/js/node/tty.js +++ b/src/js/node/tty.js @@ -4,7 +4,7 @@ const { ttySetMode, isatty, getWindowSize: _getWindowSize } = $lazy("tty"); const NumberIsInteger = Number.isInteger; function ReadStream(fd) { - if (!new.target) return new ReadStream(fd); + if (!(this instanceof ReadStream)) return new ReadStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").ReadStream.$call(this, "", { @@ -99,7 +99,7 @@ function warnOnDeactivatedColors(env) { } function WriteStream(fd) { - if (!new.target) return new WriteStream(fd); + if (!(this instanceof WriteStream)) return new WriteStream(fd); if (fd >> 0 !== fd || fd < 0) throw new RangeError("fd must be a positive integer"); const stream = require("node:fs").WriteStream.$call(this, "", { From e55a53ee0ff0379acbd76b1f1722aa40c54afcfc Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:56:50 -0800 Subject: [PATCH 07/12] Reduce number of headers exposed for JSStringDecoder --- src/bun.js/bindings/JSStringDecoder.cpp | 90 ++++++++++++++++++++++++- src/bun.js/bindings/JSStringDecoder.h | 61 +---------------- src/bun.js/bindings/ZigGlobalObject.cpp | 12 +--- 3 files changed, 92 insertions(+), 71 deletions(-) diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 1a34ffae9f039b..758583878d567c 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -9,6 +9,9 @@ #include "JSDOMConvertEnumeration.h" #include #include "BunClientData.h" +#include +#include +#include namespace WebCore { @@ -22,6 +25,66 @@ static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastChar); static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastNeed); static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastTotal); +class JSStringDecoderPrototype : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSStringDecoderPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSStringDecoderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderPrototype(vm, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSStringDecoderPrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +class JSStringDecoderConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSStringDecoderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype); + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); + DECLARE_EXPORT_INFO; + +private: + JSStringDecoderConstructor(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure, call, construct) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); +}; + static inline JSC::EncodedJSValue jsStringDecoderCast(JSGlobalObject* globalObject, JSValue stringDecoderValue) { if (LIKELY(jsDynamicCast(stringDecoderValue))) @@ -507,7 +570,7 @@ void JSStringDecoderConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* glo JSStringDecoderConstructor* JSStringDecoderConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype) { - JSStringDecoderConstructor* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderConstructor(vm, structure, construct); + JSStringDecoderConstructor* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderConstructor(vm, structure); ptr->finishCreation(vm, globalObject, prototype); return ptr; } @@ -550,6 +613,11 @@ JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* l return JSC::JSValue::encode(jsObject); } +JSC::EncodedJSValue JSStringDecoderConstructor::call(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) +{ + return JSC::JSValue::encode(jsUndefined()); +} + void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -561,4 +629,24 @@ void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObjec const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) }; +void setJSStringDecoderLazyClassStructure(JSC::LazyClassStructure& lazy) +{ + lazy.initLater( + [](LazyClassStructure::Initializer& init) { + auto* prototype = JSStringDecoderPrototype::create( + init.vm, init.global, JSStringDecoderPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); + auto* structure = JSStringDecoder::createStructure(init.vm, init.global, prototype); + auto* constructor = JSStringDecoderConstructor::create( + init.vm, init.global, JSStringDecoderConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); + }); +} + +void JSStringDecoder::destroy(JSCell* cell) +{ + static_cast(cell)->JSStringDecoder::~JSStringDecoder(); +} + } // namespace Zig diff --git a/src/bun.js/bindings/JSStringDecoder.h b/src/bun.js/bindings/JSStringDecoder.h index cd2e017d693086..0e2b40ee835454 100644 --- a/src/bun.js/bindings/JSStringDecoder.h +++ b/src/bun.js/bindings/JSStringDecoder.h @@ -46,7 +46,7 @@ class JSStringDecoder : public JSC::JSDestructibleObject { } void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject); - static void destroy(JSCell*) {} + static void destroy(JSCell*); JSC::JSValue write(JSC::VM&, JSC::JSGlobalObject*, uint8_t*, uint32_t); JSC::JSValue end(JSC::VM&, JSC::JSGlobalObject*, uint8_t*, uint32_t); @@ -63,63 +63,6 @@ class JSStringDecoder : public JSC::JSDestructibleObject { BufferEncodingType m_encoding; }; -class JSStringDecoderPrototype : public JSC::JSNonFinalObject { -public: - using Base = JSC::JSNonFinalObject; - static JSStringDecoderPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSStringDecoderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderPrototype(vm, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, Base); - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - -private: - JSStringDecoderPrototype(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); -}; - -class JSStringDecoderConstructor final : public JSC::InternalFunction { -public: - using Base = JSC::InternalFunction; - static JSStringDecoderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - DECLARE_EXPORT_INFO; - -private: - JSStringDecoderConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) - : Base(vm, structure, nativeFunction, nativeFunction) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); -}; +void setJSStringDecoderLazyClassStructure(JSC::LazyClassStructure&); } diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 5b8a5fae07960f..cca2b814ea1736 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -3321,17 +3321,7 @@ void GlobalObject::finishCreation(VM& vm) init.setStructure(structure); }); - m_JSStringDecoderClassStructure.initLater( - [](LazyClassStructure::Initializer& init) { - auto* prototype = JSStringDecoderPrototype::create( - init.vm, init.global, JSStringDecoderPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); - auto* structure = JSStringDecoder::createStructure(init.vm, init.global, prototype); - auto* constructor = JSStringDecoderConstructor::create( - init.vm, init.global, JSStringDecoderConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); - init.setPrototype(prototype); - init.setStructure(structure); - init.setConstructor(constructor); - }); + setJSStringDecoderLazyClassStructure(m_JSStringDecoderClassStructure); m_JSReadableStateClassStructure.initLater( [](LazyClassStructure::Initializer& init) { From 3223a77158ead2020015ec933917aa3b106b1f20 Mon Sep 17 00:00:00 2001 From: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:16:16 -0800 Subject: [PATCH 08/12] Add missing header --- src/bun.js/bindings/JSStringDecoder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 758583878d567c..783dafc3e0d86a 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace WebCore { From 20158519c474999c66986cbc682c39b54531254f Mon Sep 17 00:00:00 2001 From: dave caruso Date: Tue, 5 Dec 2023 13:42:38 -0800 Subject: [PATCH 09/12] Revert "Add missing header" This reverts commit 3223a77158ead2020015ec933917aa3b106b1f20. --- src/bun.js/bindings/JSStringDecoder.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 783dafc3e0d86a..758583878d567c 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -12,7 +12,6 @@ #include #include #include -#include namespace WebCore { From 3449d6c5a8da1bd9edb73fa7a43f511334f6fc4d Mon Sep 17 00:00:00 2001 From: dave caruso Date: Tue, 5 Dec 2023 13:42:40 -0800 Subject: [PATCH 10/12] Revert "Reduce number of headers exposed for JSStringDecoder" This reverts commit e55a53ee0ff0379acbd76b1f1722aa40c54afcfc. --- src/bun.js/bindings/JSStringDecoder.cpp | 90 +------------------------ src/bun.js/bindings/JSStringDecoder.h | 61 ++++++++++++++++- src/bun.js/bindings/ZigGlobalObject.cpp | 12 +++- 3 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index 758583878d567c..1a34ffae9f039b 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -9,9 +9,6 @@ #include "JSDOMConvertEnumeration.h" #include #include "BunClientData.h" -#include -#include -#include namespace WebCore { @@ -25,66 +22,6 @@ static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastChar); static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastNeed); static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastTotal); -class JSStringDecoderPrototype : public JSC::JSNonFinalObject { -public: - using Base = JSC::JSNonFinalObject; - static JSStringDecoderPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) - { - JSStringDecoderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderPrototype(vm, structure); - ptr->finishCreation(vm, globalObject); - return ptr; - } - - DECLARE_INFO; - template - static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) - { - STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, Base); - return &vm.plainObjectSpace(); - } - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); - } - -private: - JSStringDecoderPrototype(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject*); -}; - -class JSStringDecoderConstructor final : public JSC::InternalFunction { -public: - using Base = JSC::InternalFunction; - static JSStringDecoderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype); - - static constexpr unsigned StructureFlags = Base::StructureFlags; - static constexpr bool needsDestruction = false; - - static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) - { - return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); - } - - void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); - - // Must be defined for each specialization class. - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); - static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES call(JSC::JSGlobalObject*, JSC::CallFrame*); - DECLARE_EXPORT_INFO; - -private: - JSStringDecoderConstructor(JSC::VM& vm, JSC::Structure* structure) - : Base(vm, structure, call, construct) - { - } - - void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); -}; - static inline JSC::EncodedJSValue jsStringDecoderCast(JSGlobalObject* globalObject, JSValue stringDecoderValue) { if (LIKELY(jsDynamicCast(stringDecoderValue))) @@ -570,7 +507,7 @@ void JSStringDecoderConstructor::finishCreation(VM& vm, JSC::JSGlobalObject* glo JSStringDecoderConstructor* JSStringDecoderConstructor::create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype) { - JSStringDecoderConstructor* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderConstructor(vm, structure); + JSStringDecoderConstructor* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderConstructor(vm, structure, construct); ptr->finishCreation(vm, globalObject, prototype); return ptr; } @@ -613,11 +550,6 @@ JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* l return JSC::JSValue::encode(jsObject); } -JSC::EncodedJSValue JSStringDecoderConstructor::call(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame) -{ - return JSC::JSValue::encode(jsUndefined()); -} - void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype) { putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); @@ -629,24 +561,4 @@ void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObjec const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) }; -void setJSStringDecoderLazyClassStructure(JSC::LazyClassStructure& lazy) -{ - lazy.initLater( - [](LazyClassStructure::Initializer& init) { - auto* prototype = JSStringDecoderPrototype::create( - init.vm, init.global, JSStringDecoderPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); - auto* structure = JSStringDecoder::createStructure(init.vm, init.global, prototype); - auto* constructor = JSStringDecoderConstructor::create( - init.vm, init.global, JSStringDecoderConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); - init.setPrototype(prototype); - init.setStructure(structure); - init.setConstructor(constructor); - }); -} - -void JSStringDecoder::destroy(JSCell* cell) -{ - static_cast(cell)->JSStringDecoder::~JSStringDecoder(); -} - } // namespace Zig diff --git a/src/bun.js/bindings/JSStringDecoder.h b/src/bun.js/bindings/JSStringDecoder.h index 0e2b40ee835454..cd2e017d693086 100644 --- a/src/bun.js/bindings/JSStringDecoder.h +++ b/src/bun.js/bindings/JSStringDecoder.h @@ -46,7 +46,7 @@ class JSStringDecoder : public JSC::JSDestructibleObject { } void finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject); - static void destroy(JSCell*); + static void destroy(JSCell*) {} JSC::JSValue write(JSC::VM&, JSC::JSGlobalObject*, uint8_t*, uint32_t); JSC::JSValue end(JSC::VM&, JSC::JSGlobalObject*, uint8_t*, uint32_t); @@ -63,6 +63,63 @@ class JSStringDecoder : public JSC::JSDestructibleObject { BufferEncodingType m_encoding; }; -void setJSStringDecoderLazyClassStructure(JSC::LazyClassStructure&); +class JSStringDecoderPrototype : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSStringDecoderPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure) + { + JSStringDecoderPrototype* ptr = new (NotNull, JSC::allocateCell(vm)) JSStringDecoderPrototype(vm, structure); + ptr->finishCreation(vm, globalObject); + return ptr; + } + + DECLARE_INFO; + template + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSStringDecoderPrototype(JSC::VM& vm, JSC::Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject*); +}; + +class JSStringDecoderConstructor final : public JSC::InternalFunction { +public: + using Base = JSC::InternalFunction; + static JSStringDecoderConstructor* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure, JSStringDecoderPrototype* prototype); + + static constexpr unsigned StructureFlags = Base::StructureFlags; + static constexpr bool needsDestruction = false; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::InternalFunctionType, StructureFlags), info()); + } + + void initializeProperties(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); + + // Must be defined for each specialization class. + static JSC::EncodedJSValue JSC_HOST_CALL_ATTRIBUTES construct(JSC::JSGlobalObject*, JSC::CallFrame*); + DECLARE_EXPORT_INFO; + +private: + JSStringDecoderConstructor(JSC::VM& vm, JSC::Structure* structure, JSC::NativeFunction nativeFunction) + : Base(vm, structure, nativeFunction, nativeFunction) + { + } + + void finishCreation(JSC::VM&, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype); +}; } diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index cca2b814ea1736..5b8a5fae07960f 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -3321,7 +3321,17 @@ void GlobalObject::finishCreation(VM& vm) init.setStructure(structure); }); - setJSStringDecoderLazyClassStructure(m_JSStringDecoderClassStructure); + m_JSStringDecoderClassStructure.initLater( + [](LazyClassStructure::Initializer& init) { + auto* prototype = JSStringDecoderPrototype::create( + init.vm, init.global, JSStringDecoderPrototype::createStructure(init.vm, init.global, init.global->objectPrototype())); + auto* structure = JSStringDecoder::createStructure(init.vm, init.global, prototype); + auto* constructor = JSStringDecoderConstructor::create( + init.vm, init.global, JSStringDecoderConstructor::createStructure(init.vm, init.global, init.global->functionPrototype()), prototype); + init.setPrototype(prototype); + init.setStructure(structure); + init.setConstructor(constructor); + }); m_JSReadableStateClassStructure.initLater( [](LazyClassStructure::Initializer& init) { From 0867ae8b4000d39fb3817e119c34d23a82234c7c Mon Sep 17 00:00:00 2001 From: dave caruso Date: Tue, 5 Dec 2023 13:42:53 -0800 Subject: [PATCH 11/12] Revert "Faster napi" This reverts commit 5535a5ce7610651b2c0f9eec8cdb74cc69e35135. --- src/bun.js/bindings/ZigGlobalObject.cpp | 20 +--- src/bun.js/bindings/ZigGlobalObject.h | 5 - src/bun.js/bindings/napi.cpp | 153 ++++-------------------- src/bun.js/bindings/napi.h | 8 +- src/bun.js/bindings/napi_external.cpp | 2 +- src/bun.js/bindings/napi_external.h | 32 +---- src/napi/napi.zig | 2 +- 7 files changed, 36 insertions(+), 186 deletions(-) diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 5b8a5fae07960f..511d7ea6a81f13 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -137,7 +137,7 @@ #include "BunObject.h" #include "JSNextTickQueue.h" #include "NodeHTTP.h" -#include "napi_external.h" + using namespace Bun; extern "C" JSC__JSValue Bun__NodeUtil__jsParseArgs(JSC::JSGlobalObject*, JSC::CallFrame*); @@ -3061,22 +3061,6 @@ void GlobalObject::finishCreation(VM& vm) this->initGeneratedLazyClasses(); - m_NapiExternalStructure.initLater( - [](const JSC::LazyProperty::Initializer& init) { - auto& global = *reinterpret_cast(init.owner); - - init.set( - Bun::NapiExternal::createStructure(init.vm, init.owner, init.owner->objectPrototype())); - }); - - m_NapiPrototypeStructure.initLater( - [](const JSC::LazyProperty::Initializer& init) { - auto& global = *reinterpret_cast(init.owner); - - init.set( - Bun::NapiPrototype::createStructure(init.vm, init.owner, init.owner->objectPrototype())); - }); - m_cachedGlobalObjectStructure.initLater( [](const JSC::LazyProperty::Initializer& init) { auto& global = *reinterpret_cast(init.owner); @@ -3947,8 +3931,6 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_JSSocketAddressStructure.visit(visitor); thisObject->m_cachedGlobalObjectStructure.visit(visitor); thisObject->m_cachedGlobalProxyStructure.visit(visitor); - thisObject->m_NapiExternalStructure.visit(visitor); - thisObject->m_NapiPrototypeStructure.visit(visitor); thisObject->mockModule.mockFunctionStructure.visit(visitor); thisObject->mockModule.mockResultStructure.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 6c3b78920d17ab..40004b9f8444a8 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -258,9 +258,6 @@ class GlobalObject : public JSC::JSGlobalObject { JSWeakMap* vmModuleContextMap() { return m_vmModuleContextMap.getInitializedOnMainThread(this); } - Structure* NapiExternalStructure() { return m_NapiExternalStructure.getInitializedOnMainThread(this); } - Structure* NapiPrototypeStructure() { return m_NapiPrototypeStructure.getInitializedOnMainThread(this); } - bool hasProcessObject() const { return m_processObject.isInitialized(); } JSC::JSObject* processObject() { return m_processObject.getInitializedOnMainThread(this); } @@ -518,8 +515,6 @@ class GlobalObject : public JSC::JSGlobalObject { LazyProperty m_asyncBoundFunctionStructure; LazyProperty m_JSDOMFileConstructor; LazyProperty m_JSCryptoKey; - LazyProperty m_NapiExternalStructure; - LazyProperty m_NapiPrototypeStructure; LazyProperty m_bunObject; LazyProperty m_cryptoObject; diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index 9e6f0c9e03f3ae..47353f331eb777 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -59,26 +59,6 @@ using namespace JSC; using namespace Zig; -#define NAPI_VERBOSE 0 - -#if !OS(WINDOWS) -#if NAPI_VERBOSE -#include - -#define NAPI_PREMABLE \ - printf("[napi] %s:%d:%s\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); -#else - -#endif - -#ifndef NAPI_PREMABLE - -#define NAPI_PREMABLE - -#endif - -#endif - namespace Napi { JSC::SourceCode generateSourceCode(WTF::String keyString, JSC::VM& vm, JSC::JSObject* object, JSC::JSGlobalObject* globalObject) @@ -181,8 +161,17 @@ void NapiRef::clear() // namespace Napi { // class Reference // } - -extern "C" Zig::GlobalObject* Bun__getDefaultGlobal(); +#define StackAllocatedCallFramePointerTag 62 +typedef struct StackAllocatedCallFrame { + void* dataPtr; + JSC::EncodedJSValue thisValue; + // this is "bar" in: + // set foo(bar) + JSC::EncodedJSValue argument1; +} StackAllocatedCallFrame; + +extern "C" Zig::GlobalObject* +Bun__getDefaultGlobal(); WTF_MAKE_ISO_ALLOCATED_IMPL(NapiRef); @@ -325,8 +314,6 @@ static void defineNapiProperty(Zig::GlobalObject* globalObject, JSC::JSObject* t extern "C" napi_status napi_set_property(napi_env env, napi_value target, napi_value key, napi_value value) { - NAPI_PREMABLE - if (UNLIKELY(!env || !target || !key)) { return napi_invalid_arg; } @@ -351,8 +338,6 @@ extern "C" napi_status napi_set_property(napi_env env, napi_value target, extern "C" napi_status napi_has_property(napi_env env, napi_value object, napi_value key, bool* result) { - NAPI_PREMABLE - if (UNLIKELY(!object || !env)) { return napi_invalid_arg; } @@ -375,8 +360,6 @@ extern "C" napi_status napi_has_property(napi_env env, napi_value object, extern "C" napi_status napi_get_property(napi_env env, napi_value object, napi_value key, napi_value* result) { - NAPI_PREMABLE - auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -399,8 +382,6 @@ extern "C" napi_status napi_get_property(napi_env env, napi_value object, extern "C" napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool* result) { - NAPI_PREMABLE - auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -420,8 +401,6 @@ extern "C" napi_status napi_delete_property(napi_env env, napi_value object, extern "C" napi_status napi_has_own_property(napi_env env, napi_value object, napi_value key, bool* result) { - NAPI_PREMABLE - auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -443,8 +422,6 @@ extern "C" napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, napi_value value) { - NAPI_PREMABLE - auto globalObject = toJS(env); auto target = toJS(object).getObject(); auto& vm = globalObject->vm(); @@ -475,8 +452,6 @@ extern "C" napi_status napi_create_arraybuffer(napi_env env, napi_value* result) { - NAPI_PREMABLE - JSC::JSGlobalObject* globalObject = toJS(env); if (UNLIKELY(!globalObject || !result)) { return napi_invalid_arg; @@ -516,7 +491,6 @@ extern "C" napi_status napi_has_named_property(napi_env env, napi_value object, const char* utf8name, bool* result) { - NAPI_PREMABLE auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -539,7 +513,6 @@ extern "C" napi_status napi_get_named_property(napi_env env, napi_value object, const char* utf8name, napi_value* result) { - NAPI_PREMABLE auto globalObject = toJS(env); auto& vm = globalObject->vm(); @@ -698,8 +671,6 @@ extern "C" napi_status napi_wrap(napi_env env, napi_ref* result) { - NAPI_PREMABLE - JSValue value = toJS(js_object); if (!value || value.isUndefinedOrNull()) { return napi_object_expected; @@ -752,8 +723,6 @@ extern "C" napi_status napi_wrap(napi_env env, extern "C" napi_status napi_remove_wrap(napi_env env, napi_value js_object, void** result) { - NAPI_PREMABLE - JSValue value = toJS(js_object); if (!value || value.isUndefinedOrNull()) { return napi_object_expected; @@ -791,8 +760,6 @@ extern "C" napi_status napi_remove_wrap(napi_env env, napi_value js_object, extern "C" napi_status napi_unwrap(napi_env env, napi_value js_object, void** result) { - NAPI_PREMABLE - JSValue value = toJS(js_object); if (!value.isObject()) { @@ -820,7 +787,6 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name, size_t length, napi_callback cb, void* data, napi_value* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -865,8 +831,6 @@ extern "C" napi_status napi_get_cb_info( napi_value* this_arg, // [out] Receives the JS 'this' arg for the call void** data) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); auto inputArgsCount = argc == nullptr ? 0 : *argc; JSC::CallFrame* callFrame = reinterpret_cast(cbinfo); @@ -972,7 +936,6 @@ extern "C" napi_status napi_throw_error(napi_env env, const char* code, const char* msg) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -988,7 +951,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, uint32_t initial_refcount, napi_ref* result) { - NAPI_PREMABLE + JSC::JSValue val = toJS(value); if (!val || !val.isObject()) { @@ -1028,7 +991,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, extern "C" void napi_set_ref(NapiRef* ref, JSC__JSValue val_) { - NAPI_PREMABLE + JSC::JSValue val = JSC::JSValue::decode(val_); if (val) { ref->strongRef.set(ref->globalObject->vm(), val); @@ -1043,7 +1006,6 @@ extern "C" napi_status napi_add_finalizer(napi_env env, napi_value js_object, void* finalize_hint, napi_ref* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1063,7 +1025,6 @@ extern "C" napi_status napi_add_finalizer(napi_env env, napi_value js_object, extern "C" napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { - NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->unref(); *result = napiRef->refCount; @@ -1076,7 +1037,6 @@ extern "C" napi_status napi_reference_unref(napi_env env, napi_ref ref, extern "C" napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result) { - NAPI_PREMABLE NapiRef* napiRef = toJS(ref); *result = toNapi(napiRef->value()); @@ -1085,14 +1045,12 @@ extern "C" napi_status napi_get_reference_value(napi_env env, napi_ref ref, extern "C" JSC__JSValue napi_get_reference_value_internal(NapiRef* napiRef) { - NAPI_PREMABLE return JSC::JSValue::encode(napiRef->value()); } extern "C" napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { - NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->ref(); *result = napiRef->refCount; @@ -1101,7 +1059,6 @@ extern "C" napi_status napi_reference_ref(napi_env env, napi_ref ref, extern "C" napi_status napi_delete_reference(napi_env env, napi_ref ref) { - NAPI_PREMABLE NapiRef* napiRef = toJS(ref); napiRef->~NapiRef(); return napi_ok; @@ -1109,7 +1066,6 @@ extern "C" napi_status napi_delete_reference(napi_env env, napi_ref ref) extern "C" void napi_delete_reference_internal(napi_ref ref) { - NAPI_PREMABLE NapiRef* napiRef = toJS(ref); delete napiRef; } @@ -1118,7 +1074,6 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env, napi_value arraybuffer, bool* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1136,7 +1091,6 @@ extern "C" napi_status napi_is_detached_arraybuffer(napi_env env, extern "C" napi_status napi_detach_arraybuffer(napi_env env, napi_value arraybuffer) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1160,7 +1114,6 @@ extern "C" napi_status napi_adjust_external_memory(napi_env env, int64_t change_in_bytes, int64_t* adjusted_value) { - NAPI_PREMABLE if (change_in_bytes > 0) { toJS(env)->vm().heap.deprecatedReportExtraMemory(change_in_bytes); } @@ -1170,7 +1123,6 @@ extern "C" napi_status napi_adjust_external_memory(napi_env env, extern "C" napi_status napi_is_exception_pending(napi_env env, bool* result) { - NAPI_PREMABLE auto globalObject = toJS(env); *result = globalObject->vm().exceptionForInspection() != nullptr; return napi_ok; @@ -1178,7 +1130,6 @@ extern "C" napi_status napi_is_exception_pending(napi_env env, bool* result) extern "C" napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result) { - NAPI_PREMABLE auto globalObject = toJS(env); *result = toNapi(JSC::JSValue(globalObject->vm().lastException())); globalObject->vm().clearLastException(); @@ -1188,7 +1139,6 @@ extern "C" napi_status napi_get_and_clear_last_exception(napi_env env, extern "C" napi_status napi_fatal_exception(napi_env env, napi_value err) { - NAPI_PREMABLE auto globalObject = toJS(env); JSC::JSValue value = toJS(err); JSC::JSObject* obj = value.getObject(); @@ -1203,7 +1153,6 @@ extern "C" napi_status napi_fatal_exception(napi_env env, extern "C" napi_status napi_throw(napi_env env, napi_value error) { - NAPI_PREMABLE auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1222,7 +1171,6 @@ extern "C" napi_status node_api_symbol_for(napi_env env, const char* utf8description, size_t length, napi_value* result) { - NAPI_PREMABLE auto* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); if (UNLIKELY(!result || !utf8description)) { @@ -1240,7 +1188,6 @@ extern "C" napi_status node_api_create_syntax_error(napi_env env, napi_value msg, napi_value* result) { - NAPI_PREMABLE if (UNLIKELY(!result)) { return napi_invalid_arg; } @@ -1262,8 +1209,6 @@ extern "C" napi_status node_api_throw_syntax_error(napi_env env, const char* code, const char* msg) { - NAPI_PREMABLE - auto message = msg ? WTF::String::fromUTF8(msg) : String(); auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1280,7 +1225,6 @@ extern "C" napi_status node_api_throw_syntax_error(napi_env env, extern "C" napi_status napi_throw_type_error(napi_env env, const char* code, const char* msg) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1315,7 +1259,6 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, napi_value msg, napi_value* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1323,10 +1266,6 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, JSC::JSValue messageValue = toJS(msg); WTF::String message = messageValue.toWTFString(globalObject); - if (message.isEmpty()) { - message = "Error"_s; - } - auto* error = JSC::createError(globalObject, message); if (codeValue) { error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); @@ -1338,7 +1277,6 @@ extern "C" napi_status napi_create_error(napi_env env, napi_value code, extern "C" napi_status napi_throw_range_error(napi_env env, const char* code, const char* msg) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1352,7 +1290,6 @@ extern "C" napi_status napi_throw_range_error(napi_env env, const char* code, extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1373,7 +1310,6 @@ extern "C" napi_status napi_object_freeze(napi_env env, napi_value object_value) } extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1395,8 +1331,6 @@ extern "C" napi_status napi_object_seal(napi_env env, napi_value object_value) extern "C" napi_status napi_get_global(napi_env env, napi_value* result) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); *result = reinterpret_cast(globalObject->globalThis()); @@ -1407,7 +1341,6 @@ extern "C" napi_status napi_create_range_error(napi_env env, napi_value code, napi_value msg, napi_value* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1426,7 +1359,6 @@ extern "C" napi_status napi_get_new_target(napi_env env, napi_callback_info cbinfo, napi_value* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); // handle: @@ -1447,7 +1379,6 @@ extern "C" napi_status napi_create_dataview(napi_env env, size_t length, size_t byte_offset, napi_value* result) { - NAPI_PREMABLE Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1610,7 +1541,7 @@ void NapiClass::finishCreation(VM& vm, NativeExecutable* executable, unsigned le prototypePropertyCount += property.attributes & napi_static ? 0 : 1; } - NapiPrototype* prototype = NapiPrototype::create(vm, globalObject->NapiPrototypeStructure()); + NapiPrototype* prototype = NapiPrototype::create(vm, globalObject); auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -1668,7 +1599,6 @@ static napi_extended_error_info last_error_info; extern "C" napi_status napi_get_last_error_info(napi_env env, const napi_extended_error_info** result) { - NAPI_PREMABLE auto globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto lastException = vm.lastException(); @@ -1703,8 +1633,6 @@ extern "C" napi_status napi_define_class(napi_env env, const napi_property_descriptor* properties, napi_value* result) { - NAPI_PREMABLE - if (utf8name == nullptr) { return napi_invalid_arg; } @@ -1729,7 +1657,6 @@ extern "C" napi_status napi_define_class(napi_env env, extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result) { - NAPI_PREMABLE if (UNLIKELY(result == nullptr || value == nullptr || env == nullptr)) { return napi_invalid_arg; } @@ -1757,7 +1684,7 @@ extern "C" napi_status napi_coerce_to_string(napi_env env, napi_value value, extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) { - NAPI_PREMABLE + Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1787,8 +1714,6 @@ extern "C" napi_status napi_create_external_buffer(napi_env env, size_t length, void* finalize_hint, napi_value* result) { - - NAPI_PREMABLE if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1812,8 +1737,6 @@ extern "C" napi_status napi_create_external_buffer(napi_env env, size_t length, extern "C" napi_status napi_create_external_arraybuffer(napi_env env, void* external_data, size_t byte_length, napi_finalize finalize_cb, void* finalize_hint, napi_value* result) { - NAPI_PREMABLE - if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1839,8 +1762,6 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, size_t bufsize, size_t* writtenPtr) { - NAPI_PREMABLE - JSGlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -1902,8 +1823,6 @@ extern "C" napi_status napi_get_value_string_utf8(napi_env env, extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, uint32_t index, napi_value* result) { - NAPI_PREMABLE - JSValue jsValue = toJS(objectValue); if (UNLIKELY(!env || !jsValue || !jsValue.isObject())) { return napi_invalid_arg; @@ -1925,8 +1844,6 @@ extern "C" napi_status napi_get_element(napi_env env, napi_value objectValue, extern "C" napi_status napi_create_object(napi_env env, napi_value* result) { - NAPI_PREMABLE - if (UNLIKELY(result == nullptr || env == nullptr)) { return napi_invalid_arg; } @@ -1934,7 +1851,7 @@ extern "C" napi_status napi_create_object(napi_env env, napi_value* result) Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - JSValue value = JSValue(NapiPrototype::create(vm, globalObject->NapiPrototypeStructure())); + JSValue value = JSValue(NapiPrototype::create(vm, globalObject)); *result = toNapi(value); JSC::EnsureStillAliveScope ensureStillAlive(value); @@ -1946,7 +1863,6 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, void* finalize_hint, napi_value* result) { - NAPI_PREMABLE if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -1954,9 +1870,9 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); - auto* structure = globalObject->NapiExternalStructure(); - JSValue value = Bun::NapiExternal::create(vm, structure, data, finalize_hint, reinterpret_cast(finalize_cb)); - JSC::EnsureStillAliveScope ensureStillAlive(value); + auto* structure = Bun::NapiExternal::createStructure(vm, globalObject, globalObject->objectPrototype()); + JSValue value = JSValue(Bun::NapiExternal::create(vm, structure, data, finalize_hint, finalize_cb)); + *result = toNapi(value); return napi_ok; } @@ -1964,8 +1880,6 @@ extern "C" napi_status napi_create_external(napi_env env, void* data, extern "C" napi_status napi_typeof(napi_env env, napi_value val, napi_valuetype* result) { - NAPI_PREMABLE - if (UNLIKELY(result == nullptr)) return napi_invalid_arg; @@ -2026,8 +1940,6 @@ extern "C" napi_status napi_typeof(napi_env env, napi_value val, *result = napi_object; return napi_ok; } - - break; } } } @@ -2061,8 +1973,6 @@ extern "C" napi_status napi_get_value_bigint_words(napi_env env, size_t* word_count, uint64_t* words) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); JSC::JSValue jsValue = toJS(value); @@ -2102,8 +2012,6 @@ extern "C" napi_status napi_get_value_bigint_words(napi_env env, extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, void** result) { - NAPI_PREMABLE - if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; } @@ -2121,8 +2029,6 @@ extern "C" napi_status napi_get_value_external(napi_env env, napi_value value, extern "C" napi_status napi_get_instance_data(napi_env env, void** data) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); if (UNLIKELY(data == nullptr)) { return napi_invalid_arg; @@ -2137,8 +2043,6 @@ extern "C" napi_status napi_set_instance_data(napi_env env, napi_finalize finalize_cb, void* finalize_hint) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); if (data) globalObject->napiInstanceData = data; @@ -2155,8 +2059,6 @@ extern "C" napi_status napi_create_bigint_words(napi_env env, const uint64_t* words, napi_value* result) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); auto* bigint = JSC::JSBigInt::tryCreateWithLength(vm, word_count); @@ -2183,8 +2085,6 @@ extern "C" napi_status napi_create_bigint_words(napi_env env, extern "C" napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -2218,8 +2118,6 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, const napi_value* argv, napi_value* result_ptr) { - NAPI_PREMABLE - Zig::GlobalObject* globalObject = toJS(env); JSC::VM& vm = globalObject->vm(); @@ -2241,21 +2139,14 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv_napi, } JSC::JSValue thisValue = toJS(recv_napi); - auto scope = DECLARE_THROW_SCOPE(vm); if (thisValue.isEmpty()) { thisValue = JSC::jsUndefined(); } JSC::JSValue result = call(globalObject, funcValue, callData, thisValue, args); if (result_ptr) { - if (result.isEmpty()) { - *result_ptr = toNapi(JSC::jsUndefined()); - } else { - *result_ptr = toNapi(result); - } + *result_ptr = toNapi(result); } - RETURN_IF_EXCEPTION(scope, napi_generic_failure); - - RELEASE_AND_RETURN(scope, napi_ok); -} + return napi_ok; +} \ No newline at end of file diff --git a/src/bun.js/bindings/napi.h b/src/bun.js/bindings/napi.h index da64bb72902659..dfcdc8bf531526 100644 --- a/src/bun.js/bindings/napi.h +++ b/src/bun.js/bindings/napi.h @@ -192,13 +192,19 @@ class NapiPrototype : public JSC::JSDestructibleObject { DECLARE_INFO; - static NapiPrototype* create(VM& vm, Structure* structure) + static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure) { NapiPrototype* footprint = new (NotNull, allocateCell(vm)) NapiPrototype(vm, structure); footprint->finishCreation(vm); return footprint; } + static NapiPrototype* create(VM& vm, JSGlobalObject* globalObject) + { + Structure* structure = createStructure(vm, globalObject, globalObject->objectPrototype()); + return create(vm, globalObject, structure); + } + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { ASSERT(globalObject); diff --git a/src/bun.js/bindings/napi_external.cpp b/src/bun.js/bindings/napi_external.cpp index bffa96cf6dcad3..8b4798d6f328a0 100644 --- a/src/bun.js/bindings/napi_external.cpp +++ b/src/bun.js/bindings/napi_external.cpp @@ -6,7 +6,7 @@ namespace Bun { NapiExternal::~NapiExternal() { if (finalizer) { - reinterpret_cast(finalizer)(toNapi(globalObject()), m_value, m_finalizerHint); + finalizer(toNapi(globalObject()), m_value, m_finalizerHint); } } diff --git a/src/bun.js/bindings/napi_external.h b/src/bun.js/bindings/napi_external.h index c4826b3037a921..30924fa34799bb 100644 --- a/src/bun.js/bindings/napi_external.h +++ b/src/bun.js/bindings/napi_external.h @@ -6,6 +6,7 @@ #include "BunBuiltinNames.h" #include "BunClientData.h" +#include "node_api.h" namespace Bun { @@ -47,33 +48,14 @@ class NapiExternal : public JSC::JSDestructibleObject { JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); } - static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure, void* value, void* finalizer_hint, void* finalizer) + static NapiExternal* create(JSC::VM& vm, JSC::Structure* structure, void* value, void* finalizer_hint, napi_finalize finalizer) { NapiExternal* accessor = new (NotNull, JSC::allocateCell(vm)) NapiExternal(vm, structure); - accessor->finishCreation(vm, value, finalizer_hint, finalizer); - -#if BUN_DEBUG - if (auto* callFrame = vm.topCallFrame) { - auto origin = callFrame->callerSourceOrigin(vm); - accessor->sourceOriginURL = origin.string(); - - std::unique_ptr> stackTrace = makeUnique>(); - vm.interpreter.getStackTrace(accessor, *stackTrace, 0, 20); - if (!stackTrace->isEmpty()) { - for (auto& frame : *stackTrace) { - if (frame.hasLineAndColumnInfo()) { - frame.computeLineAndColumn(accessor->sourceOriginLine, accessor->sourceOriginColumn); - break; - } - } - } - } -#endif return accessor; } - void finishCreation(JSC::VM& vm, void* value, void* finalizer_hint, void* finalizer) + void finishCreation(JSC::VM& vm, void* value, void* finalizer_hint, napi_finalize finalizer) { Base::finishCreation(vm); m_value = value; @@ -87,13 +69,7 @@ class NapiExternal : public JSC::JSDestructibleObject { void* m_value; void* m_finalizerHint; - void* finalizer; - -#if BUN_DEBUG - String sourceOriginURL = String(); - unsigned sourceOriginLine = 0; - unsigned sourceOriginColumn = 0; -#endif + napi_finalize finalizer; }; } // namespace Zig \ No newline at end of file diff --git a/src/napi/napi.zig b/src/napi/napi.zig index bebf050a9b6572..082405a55c9f81 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -620,7 +620,7 @@ pub export fn napi_new_instance(env: napi_env, constructor: napi_value, argc: us pub export fn napi_instanceof(env: napi_env, object: napi_value, constructor: napi_value, result: *bool) napi_status { log("napi_instanceof", .{}); // TODO: does this throw object_expected in node? - result.* = object.isObject() and object.isInstanceOf(env, constructor); + result.* = object.isCell() and object.isInstanceOf(env, constructor); return .ok; } pub extern fn napi_get_cb_info(env: napi_env, cbinfo: napi_callback_info, argc: [*c]usize, argv: *napi_value, this_arg: *napi_value, data: [*]*anyopaque) napi_status; From 831a617e49445d113fa4e592bc91a2ed7ea73a20 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Tue, 5 Dec 2023 13:43:05 -0800 Subject: [PATCH 12/12] Revert "Fix bug with syntax highlighter" This reverts commit 367cccc35ca919a60d3405573a546890c72cf364. --- src/bun.zig | 60 +++++++--------------------- test/js/bun/util/highlighter.test.ts | 6 +-- 2 files changed, 16 insertions(+), 50 deletions(-) diff --git a/src/bun.zig b/src/bun.zig index c2bcb4893ec1c4..e92ee09928cf30 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -277,7 +277,7 @@ pub const fmt = struct { var remain = text; var prev_keyword: ?Keyword = null; - outer: while (remain.len > 0) { + while (remain.len > 0) { if (js_lexer.isIdentifierStart(remain[0])) { var i: usize = 1; @@ -351,56 +351,24 @@ pub const fmt = struct { prev_keyword = null; var i: usize = 1; - while (i < remain.len and remain[i] != char) { - if (comptime char == '`') { - if (remain[i] == '$' and i + 1 < remain.len and remain[i + 1] == '{') { - const curly_start = i; - i += 2; - - while (i < remain.len and remain[i] != '}') { - if (remain[i] == '\\') { - i += 1; - } - i += 1; - } - - try writer.print(Output.prettyFmt("{s}", true), .{remain[0..curly_start]}); - try writer.writeAll("${"); - const curly_remain = QuickAndDirtyJavaScriptSyntaxHighlighter{ - .text = remain[curly_start + 2 .. i], - .enable_colors = this.enable_colors, - .limited = false, - }; - - if (curly_remain.text.len > 0) { - try curly_remain.format("", .{}, writer); - } - - if (i < remain.len and remain[i] == '}') { - i += 1; - } - try writer.writeAll("}"); - remain = remain[i..]; - i = 0; - if (remain.len > 0 and remain[0] == char) { - try writer.writeAll(Output.prettyFmt("`", true)); - remain = remain[1..]; - continue :outer; - } - continue; + for (remain[i..]) |c| { + if (c == char) { + if (i < remain.len) { + i += 1; } - } - - if (i + 1 < remain.len and remain[i] == '\\') { + break; + } else if (c == '\\') { i += 1; + if (i < remain.len) { + i += 1; + } + } else { + if (i < remain.len) { + i += 1; + } } - - i += 1; } - // Include the trailing quote, if any - i += @as(usize, @intFromBool(i > 1 and i < remain.len and remain[i] == char)); - try writer.print(Output.prettyFmt("{s}", true), .{remain[0..i]}); remain = remain[i..]; }, diff --git a/test/js/bun/util/highlighter.test.ts b/test/js/bun/util/highlighter.test.ts index af3b7abb2f5a6b..91ef6768b505d0 100644 --- a/test/js/bun/util/highlighter.test.ts +++ b/test/js/bun/util/highlighter.test.ts @@ -3,7 +3,5 @@ import { readFileSync, writeFileSync } from "fs"; // @ts-expect-error const highlighter: (code: string) => string = globalThis[Symbol.for("Bun.lazy")]("unstable_syntaxHighlight"); -test("highlighter", () => { - expect(highlighter("`can do ${123} ${'123'} ${`123`}`").length).toBeLessThan(150); - expect(highlighter("`can do ${123} ${'123'} ${`123`}`123").length).toBeLessThan(150); -}); +// TODO: write tests for syntax highlighting +test("highlighter", () => {});