diff options
author | 2022-07-04 08:41:03 -0700 | |
---|---|---|
committer | 2022-07-04 08:41:03 -0700 | |
commit | bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987 (patch) | |
tree | 7cd40a5fd5a0cb23cba1c171ba83398223cfdc55 /src | |
parent | 77b5999b73021d1b12fd9bcf2a8e8a261722ec2c (diff) | |
parent | 0f987a5601e3ec2f154607802b1e7da2ef03b770 (diff) | |
download | bun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.tar.gz bun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.tar.zst bun-bbcc08dbb44dd28f7141e6f50a7cb5edfb8b4987.zip |
Merge branch 'jarred/landing'
Diffstat (limited to 'src')
m--------- | src/bun.js/WebKit | 0 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 48 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 7 | ||||
-rw-r--r-- | src/bun.js/event_loop.zig | 8 | ||||
-rw-r--r-- | src/bun.js/fs.exports.js | 72 | ||||
-rw-r--r-- | src/bun.js/javascript.zig | 5 | ||||
-rw-r--r-- | src/bun.js/javascript_core_c_api.zig | 18 | ||||
-rw-r--r-- | src/bun.js/webcore.zig | 36 | ||||
m--------- | src/deps/uws | 0 | ||||
-rw-r--r-- | src/feature_flags.zig | 2 | ||||
-rw-r--r-- | src/js_printer.zig | 10 | ||||
-rw-r--r-- | src/sourcemap/sourcemap.zig | 6 | ||||
-rw-r--r-- | src/string_immutable.zig | 45 |
13 files changed, 190 insertions, 67 deletions
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit -Subproject a06260772abc4a9e9a984cc3654f44e0b9872b1 +Subproject 7e7774dabf1c2d94fe3604defb3c54a4c989c3b diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 1e73da3ed..138267cd6 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -1487,6 +1487,29 @@ JSC_DEFINE_HOST_FUNCTION(functionConcatTypedArrays, (JSGlobalObject * globalObje return flattenArrayOfBuffersIntoArrayBuffer(globalObject, arrayValue); } +extern "C" uint64_t Bun__readOriginTimer(void*); + +JSC_DECLARE_HOST_FUNCTION(functionPerformanceNow); + +JSC_DEFINE_HOST_FUNCTION(functionPerformanceNow, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + auto* global = reinterpret_cast<GlobalObject*>(globalObject); + // nanoseconds to seconds + uint64_t time = Bun__readOriginTimer(global->bunVM()); + double result = time / 1000000000.0; + return JSValue::encode(jsNumber(time)); +} + +JSC_DECLARE_HOST_FUNCTION(functionBunNanoseconds); + +JSC_DEFINE_HOST_FUNCTION(functionBunNanoseconds, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) +{ + auto* global = reinterpret_cast<GlobalObject*>(globalObject); + // nanoseconds to seconds + uint64_t time = Bun__readOriginTimer(global->bunVM()); + return JSValue::encode(jsNumber(time)); +} + JSC_DECLARE_HOST_FUNCTION(functionConcatTypedArraysFromIterator); JSC_DEFINE_HOST_FUNCTION(functionConcatTypedArraysFromIterator, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) @@ -1663,10 +1686,10 @@ void GlobalObject::finishCreation(VM& vm) init.set(prototype); }); - m_JSHTTPResponseControllerPrototype.initLater( - [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { - auto* prototype = createJSSinkControllerPrototype(init.vm, init.owner, WebCore::SinkID::HTTPResponseSink); - init.set(prototype); + m_JSHTTPResponseController.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::Structure>::Initializer& init) { + auto* structure = createJSSinkControllerStructure(init.vm, init.owner, WebCore::SinkID::HTTPResponseSink); + init.set(structure); }); m_JSHTTPSResponseControllerPrototype.initLater( @@ -1675,6 +1698,13 @@ void GlobalObject::finishCreation(VM& vm) init.set(prototype); }); + m_performanceObject.initLater( + [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { + JSC::JSObject* object = JSC::constructEmptyObject(init.owner, init.owner->objectPrototype(), 1); + object->putDirectNativeFunction(init.vm, init.owner, JSC::Identifier::fromString(init.vm, "now"_s), 1, functionPerformanceNow, NoIntrinsic, 0); + init.set(object); + }); + m_processEnvObject.initLater( [](const JSC::LazyProperty<JSC::JSGlobalObject, JSC::JSObject>::Initializer& init) { auto jsClass = reinterpret_cast<Zig::GlobalObject*>(init.owner)->m_dotEnvClassRef; @@ -1878,6 +1908,9 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "process"_s), JSC::CustomGetterSetter::create(vm, property_lazyProcessGetter, property_lazyProcessSetter), JSC::PropertyAttribute::CustomAccessor | 0); + putDirect(vm, JSC::Identifier::fromString(vm, "performance"_s), this->performanceObject(), + 0); + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "URL"_s), JSC::CustomGetterSetter::create(vm, JSDOMURL_getter, nullptr), JSC::PropertyAttribute::DontDelete | 0); @@ -2036,6 +2069,12 @@ void GlobalObject::installAPIGlobals(JSClassRef* globals, int count, JSC::VM& vm } { + JSC::Identifier identifier = JSC::Identifier::fromString(vm, "nanoseconds"_s); + object->putDirectNativeFunction(vm, this, identifier, 1, functionBunNanoseconds, NoIntrinsic, + JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DontDelete | 0); + } + + { JSC::Identifier identifier = JSC::Identifier::fromString(vm, pathToFileURLString); object->putDirectNativeFunction(vm, this, identifier, 1, functionPathToFileURL, NoIntrinsic, @@ -2135,6 +2174,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_requireMap.visit(visitor); thisObject->m_processEnvObject.visit(visitor); thisObject->m_processObject.visit(visitor); + thisObject->m_performanceObject.visit(visitor); visitor.append(thisObject->m_readableStreamToArrayBufferResolve); visitor.append(thisObject->m_readableStreamToText); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 47449321b..3832eb9c2 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -179,7 +179,7 @@ public: JSC::Structure* HTTPResponseSinkStructure() { return m_JSHTTPResponseSinkClassStructure.getInitializedOnMainThread(this); } JSC::JSObject* HTTPResponseSink() { return m_JSHTTPResponseSinkClassStructure.constructorInitializedOnMainThread(this); } JSC::JSValue HTTPResponseSinkPrototype() { return m_JSHTTPResponseSinkClassStructure.prototypeInitializedOnMainThread(this); } - JSC::JSValue JSReadableHTTPResponseSinkControllerPrototype() { return m_JSHTTPResponseControllerPrototype.getInitializedOnMainThread(this); } + JSC::Structure* JSReadableHTTPResponseSinkController() { return m_JSHTTPResponseController.getInitializedOnMainThread(this); } JSC::Structure* HTTPSResponseSinkStructure() { return m_JSHTTPSResponseSinkClassStructure.getInitializedOnMainThread(this); } JSC::JSObject* HTTPSResponseSink() { return m_JSHTTPSResponseSinkClassStructure.constructorInitializedOnMainThread(this); } @@ -189,6 +189,8 @@ public: JSC::JSMap* readableStreamNativeMap() { return m_lazyReadableStreamPrototypeMap.getInitializedOnMainThread(this); } JSC::JSMap* requireMap() { return m_requireMap.getInitializedOnMainThread(this); } + JSC::JSObject* performanceObject() { return m_performanceObject.getInitializedOnMainThread(this); } + JSC::JSObject* processObject() { return m_processObject.getInitializedOnMainThread(this); @@ -228,11 +230,12 @@ private: LazyProperty<JSGlobalObject, JSObject> m_JSArrayBufferControllerPrototype; LazyProperty<JSGlobalObject, JSObject> m_JSHTTPSResponseControllerPrototype; - LazyProperty<JSGlobalObject, JSObject> m_JSHTTPResponseControllerPrototype; + LazyProperty<JSGlobalObject, Structure> m_JSHTTPResponseController; LazyProperty<JSGlobalObject, JSObject> m_processObject; LazyProperty<JSGlobalObject, JSObject> m_processEnvObject; LazyProperty<JSGlobalObject, JSMap> m_lazyReadableStreamPrototypeMap; LazyProperty<JSGlobalObject, JSMap> m_requireMap; + LazyProperty<JSGlobalObject, JSObject> m_performanceObject; // LazyProperty<JSGlobalObject, WebCore::JSEventTarget> m_eventTarget; JSClassRef m_dotEnvClassRef; diff --git a/src/bun.js/event_loop.zig b/src/bun.js/event_loop.zig index 95bf5456c..df6af2748 100644 --- a/src/bun.js/event_loop.zig +++ b/src/bun.js/event_loop.zig @@ -422,7 +422,13 @@ pub const EventLoop = struct { if (this.tickWithCount() == 0) break; } - this.global.vm().releaseWeakRefs(); + // This is JSC's event loop + // We don't actually use this. + // However, there are three uses of it in JavaScriptCore outside our control: + // 1. FinalizationRegistry callbacks + // 2. WebAssembly.instantiate + // 3. WebAssembly.instantiateStreaming + this.global.vm().doWork(); if (!ctx.disable_run_us_loop and ctx.us_loop_reference_count > 0 and !ctx.is_us_loop_entered) { ctx.is_us_loop_entered = true; diff --git a/src/bun.js/fs.exports.js b/src/bun.js/fs.exports.js index 0680b3568..8eb043f69 100644 --- a/src/bun.js/fs.exports.js +++ b/src/bun.js/fs.exports.js @@ -119,6 +119,39 @@ function callbackify(fsFunction, args) { }); } +// note: this is not quite the same as how node does it +// in some cases, node swaps around arguments or makes small tweaks to the return type +// this is just better than nothing. +function promisify(fsFunction) { + // TODO: remove variadic arguments + // we can use new Function() here instead + // based on fsFucntion.length + var obj = { + [fsFunction.name]: function (resolve, reject, args) { + var result; + try { + result = fsFunction.apply(fs, args); + args = undefined; + } catch (err) { + args = undefined; + reject(err); + return; + } + + resolve(result); + }, + }; + + var func = obj[fsFunction.name]; + + // TODO: consider @createPromiseCapabiilty intrinsic + return (...args) => { + return new Promise((resolve, reject) => { + func(resolve, reject, args); + }); + }; +} + export var accessSync = fs.accessSync.bind(fs); export var appendFileSync = fs.appendFileSync.bind(fs); export var closeSync = fs.closeSync.bind(fs); @@ -157,6 +190,44 @@ export var lutimesSync = fs.lutimesSync.bind(fs); export var createReadStream = fs.createReadStream.bind(fs); export var createWriteStream = fs.createWriteStream.bind(fs); +export var promises = { + access: promisify(fs.accessSync), + appendFile: promisify(fs.appendFileSync), + close: promisify(fs.closeSync), + copyFile: promisify(fs.copyFileSync), + exists: promisify(fs.existsSync), + chown: promisify(fs.chownSync), + chmod: promisify(fs.chmodSync), + fchmod: promisify(fs.fchmodSync), + fchown: promisify(fs.fchownSync), + fstat: promisify(fs.fstatSync), + fsync: promisify(fs.fsyncSync), + ftruncate: promisify(fs.ftruncateSync), + futimes: promisify(fs.futimesSync), + lchmod: promisify(fs.lchmodSync), + lchown: promisify(fs.lchownSync), + link: promisify(fs.linkSync), + lstat: promisify(fs.lstatSync), + mkdir: promisify(fs.mkdirSync), + mkdtemp: promisify(fs.mkdtempSync), + open: promisify(fs.openSync), + read: promisify(fs.readSync), + write: promisify(fs.writeSync), + readdir: promisify(fs.readdirSync), + writeFile: promisify(fs.writeFileSync), + readlink: promisify(fs.readlinkSync), + realpath: promisify(fs.realpathSync), + rename: promisify(fs.renameSync), + stat: promisify(fs.statSync), + symlink: promisify(fs.symlinkSync), + truncate: promisify(fs.truncateSync), + unlink: promisify(fs.unlinkSync), + utimes: promisify(fs.utimesSync), + lutimes: promisify(fs.lutimesSync), +}; + +promises.readFile = promises.readfile = promisify(fs.readFileSync); + // lol realpath.native = realpath; realpathSync.native = realpathSync; @@ -233,4 +304,5 @@ export default { createReadStream, createWriteStream, constants, + promises, }; diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index 9ed16caf0..5c4f2ae68 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -258,12 +258,17 @@ pub export fn Bun__drainMicrotasks() void { JSC.VirtualMachine.vm.eventLoop().tick(); } +export fn Bun__readOriginTimer(vm: *JSC.VirtualMachine) u64 { + return vm.origin_timer.read(); +} + comptime { if (!JSC.is_bindgen) { _ = Bun__getDefaultGlobal; _ = Bun__getVM; _ = Bun__drainMicrotasks; _ = Bun__queueMicrotask; + _ = Bun__readOriginTimer; } } diff --git a/src/bun.js/javascript_core_c_api.zig b/src/bun.js/javascript_core_c_api.zig index aa9af2b7e..82145defc 100644 --- a/src/bun.js/javascript_core_c_api.zig +++ b/src/bun.js/javascript_core_c_api.zig @@ -102,15 +102,31 @@ pub extern fn JSValueToNumber(ctx: JSContextRef, value: JSValueRef, exception: E pub extern fn JSValueToStringCopy(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSStringRef; pub extern fn JSValueToObject(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSObjectRef; +const log_protection = @import("../global.zig").Environment.allow_assert; +pub inline fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void { + const Wrapped = struct { + pub extern fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void; + }; + if (comptime log_protection) { + const Output = @import("../global.zig").Output; + Output.debug("[unprotect] {d}\n", .{@ptrToInt(value)}); + } + // wrapper exists to make it easier to set a breakpoint + Wrapped.JSValueUnprotect(ctx, value); +} + pub inline fn JSValueProtect(ctx: JSContextRef, value: JSValueRef) void { const Wrapped = struct { pub extern fn JSValueProtect(ctx: JSContextRef, value: JSValueRef) void; }; + if (comptime log_protection) { + const Output = @import("../global.zig").Output; + Output.debug("[protect] {d}\n", .{@ptrToInt(value)}); + } // wrapper exists to make it easier to set a breakpoint Wrapped.JSValueProtect(ctx, value); } -pub extern fn JSValueUnprotect(ctx: JSContextRef, value: JSValueRef) void; pub const JSPropertyAttributes = enum(c_uint) { kJSPropertyAttributeNone = 0, kJSPropertyAttributeReadOnly = 2, diff --git a/src/bun.js/webcore.zig b/src/bun.js/webcore.zig index 0433402fc..981e15c8f 100644 --- a/src/bun.js/webcore.zig +++ b/src/bun.js/webcore.zig @@ -92,39 +92,3 @@ pub const Crypto = struct { return JSC.ZigString.init(str).toValueGC(ctx.ptr()).asObjectRef(); } }; - -pub const Performance = struct { - pub const Class = JSC.NewClass( - void, - .{ - .name = "performance", - .read_only = true, - }, - .{ - .now = .{ - .rfn = Performance.now, - }, - }, - .{}, - ); - - pub fn now( - _: void, - ctx: JSC.C.JSContextRef, - _: JSC.C.JSObjectRef, - _: JSC.C.JSObjectRef, - _: []const JSC.C.JSValueRef, - _: JSC.C.ExceptionRef, - ) JSC.C.JSValueRef { - return JSC.C.JSValueMakeNumber( - ctx, - @floatCast( - f64, - @intToFloat( - f128, - JSC.VirtualMachine.vm.origin_timer.read(), - ) / std.time.ns_per_ms, - ), - ); - } -}; diff --git a/src/deps/uws b/src/deps/uws -Subproject f0ea7574ab3c642bc1c0ee4991e771c1ee164f4 +Subproject 1b46cf9ace5f55f713d55bb8c086f5878d13245 diff --git a/src/feature_flags.zig b/src/feature_flags.zig index 6fe6da892..dc77a47e6 100644 --- a/src/feature_flags.zig +++ b/src/feature_flags.zig @@ -95,4 +95,4 @@ pub const simd = true; // This change didn't seem to make a meaningful difference in microbenchmarks pub const latin1_is_now_ascii = false; -pub const http_buffer_pooling = false; +pub const http_buffer_pooling = true; diff --git a/src/js_printer.zig b/src/js_printer.zig index 1a68c6662..945e0a382 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -340,8 +340,14 @@ pub fn writeJSONString(text: []const u8, comptime Writer: type, writer: Writer, test "quoteForJSON" { var allocator = default_allocator; - try std.testing.expectEqualStrings("\"I don't need any quotes.\"", try quoteForJSON("I don't need any quotes.", allocator, false)); - try std.testing.expectEqualStrings("\"I need a quote for \\\"this\\\".\"", try quoteForJSON("I need a quote for \"this\".", allocator, false)); + try std.testing.expectEqualStrings( + "\"I don't need any quotes.\"", + (try quoteForJSON("I don't need any quotes.", MutableString.init(allocator, 0) catch unreachable, false)).list.items, + ); + try std.testing.expectEqualStrings( + "\"I need a quote for \\\"this\\\".\"", + (try quoteForJSON("I need a quote for \"this\".", MutableString.init(allocator, 0) catch unreachable, false)).list.items, + ); } pub const SourceMapHandler = struct { diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig index 22a916940..92bd6189c 100644 --- a/src/sourcemap/sourcemap.zig +++ b/src/sourcemap/sourcemap.zig @@ -645,7 +645,11 @@ pub const LineOffsetTable = struct { } if (c > 0x7F and columns_for_non_ascii.items.len == 0) { - + std.debug.assert(@ptrToInt( + remaining.ptr, + ) > @ptrToInt( + contents.ptr, + )); // we have a non-ASCII character, so we need to keep track of the // mapping from byte offsets to UTF-16 code unit counts columns_for_non_ascii.appendAssumeCapacity(column); diff --git a/src/string_immutable.zig b/src/string_immutable.zig index d4dc7c6c1..5ee958b40 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -2624,19 +2624,24 @@ pub fn indexOfNewlineOrNonASCIICheckStart(slice_: []const u8, offset: u32, compt const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) | @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\r'))) | @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\n'))); - const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; - const first = @ctz(AsciiVectorInt, bitmask); - if (first < ascii_vector_size) { + + if (@reduce(.Max, cmp) > 0) { + const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; + const first = @ctz(AsciiVectorInt, bitmask); + return @as(u32, first) + @intCast(u32, slice.len - remaining.len) + offset; } remaining = remaining[ascii_vector_size..]; } + + assert(remaining.len < ascii_vector_size); } - for (remaining) |char, i| { + for (remaining) |*char_| { + const char = char_.*; if (char > 127 or char < 0x20 or char == '\n' or char == '\r') { - return @truncate(u32, i + (slice.len - remaining.len)) + offset; + return @truncate(u32, (@ptrToInt(char_) - @ptrToInt(slice.ptr))) + offset; } } @@ -2658,19 +2663,22 @@ pub fn indexOfNeedsEscape(slice: []const u8) ?u32 { const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) | @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\\'))) | @bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '"'))); - const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; - const first = @ctz(AsciiVectorInt, bitmask); - if (first < ascii_vector_size) { - return @as(u32, first) + @intCast(u32, slice.len - remaining.len); + + if (@reduce(.Max, cmp) > 0) { + const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; + const first = @ctz(AsciiVectorInt, bitmask); + + return @as(u32, first) + @truncate(u32, @ptrToInt(remaining.ptr) - @ptrToInt(slice.ptr)); } remaining = remaining[ascii_vector_size..]; } } - for (remaining) |char, i| { + for (remaining) |*char_| { + const char = char_.*; if (char > 127 or char < 0x20 or char == '\\' or char == '"') { - return @truncate(u32, i + (slice.len - remaining.len)); + return @truncate(u32, @ptrToInt(char_) - @ptrToInt(slice.ptr)); } } @@ -2762,10 +2770,10 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 { if (comptime Environment.isAarch64 or Environment.isX64) { while (remaining.len >= ascii_vector_size) { const vec: AsciiVector = remaining[0..ascii_vector_size].*; - const cmp = vec != @splat(ascii_vector_size, char); - const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; - const first = @ctz(AsciiVectorInt, bitmask); - if (first < ascii_vector_size) { + const cmp = @splat(ascii_vector_size, char) != vec; + if (@reduce(.Min, @bitCast(AsciiVectorU1, cmp)) > 0) { + const bitmask = @ptrCast(*const AsciiVectorInt, &cmp).*; + const first = @ctz(AsciiVectorInt, bitmask); return @as(u32, first) + @intCast(u32, slice.len - remaining.len); } @@ -2773,11 +2781,10 @@ pub fn indexOfNotChar(slice: []const u8, char: u8) ?u32 { } } - while (remaining.len > 0) { - if (remaining[0] != char) { - return @truncate(u32, (slice.len - remaining.len)); + for (remaining) |*current| { + if (current.* != char) { + return @truncate(u32, @ptrToInt(current) - @ptrToInt(slice.ptr)); } - remaining = remaining[1..]; } return null; |