aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-24 19:08:20 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-03-24 19:08:20 -0700
commit3434b9ecf301ad529e07b06471d0cb891ce571d3 (patch)
tree89259927ca54e85c030152b2f338fc5fdc51a60a /src/javascript/jsc
parent92a46c292f2f705eaad2a1060f468a4787f51dfd (diff)
downloadbun-3434b9ecf301ad529e07b06471d0cb891ce571d3.tar.gz
bun-3434b9ecf301ad529e07b06471d0cb891ce571d3.tar.zst
bun-3434b9ecf301ad529e07b06471d0cb891ce571d3.zip
Implement error page for HTTP server
Diffstat (limited to 'src/javascript/jsc')
-rw-r--r--src/javascript/jsc/api/server.zig164
-rw-r--r--src/javascript/jsc/base.zig475
-rw-r--r--src/javascript/jsc/javascript.zig13
-rw-r--r--src/javascript/jsc/rare_data.zig3
4 files changed, 630 insertions, 25 deletions
diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig
index 7a1cfad23..2beac4d23 100644
--- a/src/javascript/jsc/api/server.zig
+++ b/src/javascript/jsc/api/server.zig
@@ -78,6 +78,8 @@ const VirtualMachine = @import("../javascript.zig").VirtualMachine;
const IOTask = JSC.IOTask;
const is_bindgen = JSC.is_bindgen;
const uws = @import("uws");
+const Fallback = Runtime.Fallback;
+const MimeType = HTTP.MimeType;
const Blob = JSC.WebCore.Blob;
const SendfileContext = struct {
fd: i32,
@@ -154,6 +156,7 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
sendfile: SendfileContext = undefined,
request_js_object: JSC.C.JSObjectRef = null,
request_body_buf: std.ArrayListUnmanaged(u8) = .{},
+ fallback_buf: std.ArrayListUnmanaged(u8) = .{},
pub threadlocal var pool: *RequestContextStackAllocator = undefined;
@@ -194,7 +197,21 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
_: *JSC.JSGlobalObject,
arguments: []const JSC.JSValue,
) void {
- JSC.VirtualMachine.vm.defaultErrorHandler(arguments[0], null);
+ var exception_list: std.ArrayList(Api.JsException) = std.ArrayList(Api.JsException).init(bun.default_allocator);
+ JSC.VirtualMachine.vm.defaultErrorHandler(arguments[0], &exception_list);
+ if (!ctx.resp.hasResponded()) {
+ ctx.renderDefaultError(
+ JSC.VirtualMachine.vm.log,
+ error.PromiseRejection,
+ exception_list.toOwnedSlice(),
+ "",
+ .{},
+ );
+ JSC.VirtualMachine.vm.log.reset();
+ return;
+ } else {
+ exception_list.deinit();
+ }
if (ctx.aborted) {
ctx.finalize();
@@ -205,6 +222,64 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
ctx.finalize();
}
+ pub fn renderDefaultError(
+ this: *RequestContext,
+ log: *logger.Log,
+ err: anyerror,
+ exceptions: []Api.JsException,
+ comptime fmt: string,
+ args: anytype,
+ ) void {
+ this.resp.writeStatus("500 Internal Server Error");
+ this.resp.writeHeader("content-type", MimeType.html.value);
+
+ var allocator = bun.default_allocator;
+
+ var fallback_container = allocator.create(Api.FallbackMessageContainer) catch unreachable;
+ defer allocator.destroy(fallback_container);
+ fallback_container.* = Api.FallbackMessageContainer{
+ .message = std.fmt.allocPrint(allocator, fmt, args) catch unreachable,
+ .router = null,
+ .reason = .fetch_event_handler,
+ .cwd = VirtualMachine.vm.bundler.fs.top_level_dir,
+ .problems = Api.Problems{
+ .code = @truncate(u16, @errorToInt(err)),
+ .name = @errorName(err),
+ .exceptions = exceptions,
+ .build = log.toAPI(allocator) catch unreachable,
+ },
+ };
+
+ if (comptime fmt.len > 0) Output.prettyErrorln(fmt, args);
+ Output.flush();
+
+ var bb = std.ArrayList(u8).init(allocator);
+ var bb_writer = bb.writer();
+
+ Fallback.renderBackend(
+ allocator,
+ fallback_container,
+ @TypeOf(bb_writer),
+ bb_writer,
+ ) catch unreachable;
+ if (this.resp.tryEnd(bb.items, bb.items.len)) {
+ bb.clearAndFree();
+ this.finalize();
+ return;
+ }
+
+ this.fallback_buf = std.ArrayListUnmanaged(u8){ .items = bb.items, .capacity = bb.capacity };
+ this.resp.onWritable(*RequestContext, onWritableFallback, this);
+ }
+
+ pub fn onWritableFallback(this: *RequestContext, write_offset: c_ulong, resp: *App.Response) callconv(.C) bool {
+ if (this.aborted) {
+ return false;
+ }
+
+ return this.sendWritableBytes(this.fallback_buf.items, write_offset, resp);
+ }
+
pub fn create(this: *RequestContext, server: *ThisServer, req: *uws.Request, resp: *App.Response) void {
this.* = .{
.resp = resp,
@@ -257,6 +332,8 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
this.response_headers.?.deref();
this.response_headers = null;
}
+
+ this.fallback_buf.clearAndFree(bun.default_allocator);
}
pub fn finalize(this: *RequestContext) void {
this.finalizeWithoutDeinit();
@@ -370,9 +447,12 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
return false;
var bytes = this.blob.sharedView();
+ return this.sendWritableBytes(bytes, write_offset, resp);
+ }
- bytes = bytes[@minimum(bytes.len, @truncate(usize, write_offset))..];
- if (resp.tryEnd(bytes, this.blob.size)) {
+ pub fn sendWritableBytes(this: *RequestContext, bytes_: []const u8, write_offset: c_ulong, resp: *App.Response) bool {
+ var bytes = bytes_[@minimum(bytes_.len, @truncate(usize, write_offset))..];
+ if (resp.tryEnd(bytes, bytes_.len)) {
this.finalize();
return true;
} else {
@@ -583,7 +663,61 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
}
};
+ pub fn onBunInfoRequest(_: *ThisServer, req: *uws.Request, resp: *App.Response) void {
+ if (comptime JSC.is_bindgen) return undefined;
+ req.setYield(false);
+ var stack_fallback = std.heap.stackFallback(8096, bun.default_allocator);
+ var allocator = stack_fallback.get();
+
+ var buffer_writer = js_printer.BufferWriter.init(allocator) catch unreachable;
+ var writer = js_printer.BufferPrinter.init(buffer_writer);
+ defer writer.ctx.buffer.deinit();
+ var source = logger.Source.initEmptyFile("info.json");
+ _ = js_printer.printJSON(
+ *js_printer.BufferPrinter,
+ &writer,
+ bun.Global.BunInfo.generate(*Bundler, &JSC.VirtualMachine.vm.bundler, allocator) catch unreachable,
+ &source,
+ ) catch unreachable;
+
+ resp.writeStatus("200 OK");
+ resp.writeHeader("Content-Type", MimeType.json.value);
+ resp.writeHeader("Cache-Control", "public, max-age=3600");
+ resp.writeHeaderInt("Age", 0);
+ const buffer = writer.ctx.written;
+ resp.end(buffer, false);
+ }
+ pub fn onSrcRequest(_: *ThisServer, req: *uws.Request, resp: *App.Response) void {
+ if (comptime JSC.is_bindgen) return undefined;
+ req.setYield(false);
+ if (req.header("open-in-editor") == null) {
+ resp.writeStatus("501 Not Implemented");
+ resp.end("Viewing source without opening in editor is not implemented yet!", false);
+ return;
+ }
+
+ var ctx = &JSC.VirtualMachine.vm.rareData().editor_context;
+ ctx.autoDetectEditor(JSC.VirtualMachine.vm.bundler.env);
+ var line: ?string = req.header("editor-line");
+ var column: ?string = req.header("editor-column");
+
+ if (ctx.editor) |editor| {
+ resp.writeStatus("200 Opened");
+ resp.end("Opened in editor", false);
+ var url = req.url()["/src:".len..];
+ if (strings.indexOfChar(url, ':')) |colon| {
+ url = url[0..colon];
+ }
+ editor.open(ctx.path, url, line, column, bun.default_allocator) catch Output.prettyErrorln("Failed to open editor", .{});
+ } else {
+ resp.writeStatus("500 Missing Editor :(");
+ resp.end("Please set your editor in bunfig.toml", false);
+ }
+ }
+
pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void {
+ if (comptime JSC.is_bindgen) return undefined;
+
req.setYield(false);
var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory");
ctx.create(this, req, resp);
@@ -613,12 +747,30 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
return;
}
- if (ctx.response_jsvalue.isUndefinedOrNull() or ctx.response_jsvalue.isError() or ctx.response_jsvalue.isAggregateError(this.globalThis) or ctx.response_jsvalue.isException(this.globalThis.vm())) {
+ if (ctx.response_jsvalue.isUndefinedOrNull()) {
req.setYield(true);
ctx.finalize();
return;
}
+ if (ctx.response_jsvalue.isError() or ctx.response_jsvalue.isAggregateError(this.globalThis) or ctx.response_jsvalue.isException(this.globalThis.vm())) {
+ var exception_list: std.ArrayList(Api.JsException) = std.ArrayList(Api.JsException).init(bun.default_allocator);
+ JSC.VirtualMachine.vm.defaultErrorHandler(ctx.response_jsvalue, &exception_list);
+ if (!ctx.resp.hasResponded()) {
+ ctx.renderDefaultError(
+ JSC.VirtualMachine.vm.log,
+ error.ExceptionOcurred,
+ exception_list.toOwnedSlice(),
+ "Unhandled exception in request handler",
+ .{},
+ );
+ JSC.VirtualMachine.vm.log.reset();
+ return;
+ } else {
+ exception_list.deinit();
+ }
+ }
+
JSC.C.JSValueProtect(this.globalThis.ref(), ctx.response_jsvalue.asObjectRef());
if (ctx.response_jsvalue.as(JSC.WebCore.Response)) |response| {
@@ -650,6 +802,10 @@ pub fn NewServer(comptime ssl_enabled: bool) type {
pub fn listen(this: *ThisServer) void {
this.app = App.create(.{});
this.app.any("/*", *ThisServer, this, onRequest);
+
+ this.app.get("/bun:info", *ThisServer, this, onBunInfoRequest);
+ this.app.get("/src:/*", *ThisServer, this, onSrcRequest);
+
this.app.listenWithConfig(*ThisServer, this, onListen, .{
.port = this.default_server.getPort().?,
.host = bun.default_allocator.dupeZ(u8, this.default_server.displayHostname()) catch unreachable,
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig
index 13de8770d..1652df07b 100644
--- a/src/javascript/jsc/base.zig
+++ b/src/javascript/jsc/base.zig
@@ -943,9 +943,6 @@ pub fn NewClassWithInstanceType(
const class_definition_ptr = &complete_definition;
pub fn get() callconv(.C) [*c]js.JSClassRef {
- if (comptime JSC.is_bindgen)
- unreachable;
-
var lazy = lazy_ref;
if (!lazy.loaded) {
@@ -977,9 +974,6 @@ pub fn NewClassWithInstanceType(
}
pub fn make(ctx: js.JSContextRef, ptr: *ZigType) js.JSObjectRef {
- if (comptime JSC.is_bindgen)
- unreachable;
-
var real_ptr = JSPrivateDataPtr.init(ptr).ptr();
if (comptime Environment.allow_assert) {
std.debug.assert(JSPrivateDataPtr.isValidPtr(real_ptr));
@@ -1030,9 +1024,6 @@ pub fn NewClassWithInstanceType(
prop: js.JSStringRef,
exception: js.ExceptionRef,
) callconv(.C) js.JSValueRef {
- if (comptime JSC.is_bindgen)
- unreachable;
-
var this: ObjectPtrType(ZigType) = if (comptime ZigType == void) void{} else GetJSPrivateData(ZigType, obj) orelse return js.JSValueMakeUndefined(ctx);
const Field = @TypeOf(@field(
@@ -1104,9 +1095,6 @@ pub fn NewClassWithInstanceType(
value: js.JSValueRef,
exception: js.ExceptionRef,
) callconv(.C) bool {
- if (comptime JSC.is_bindgen)
- unreachable;
-
var this = GetJSPrivateData(ZigType, obj) orelse return false;
switch (comptime @typeInfo(@TypeOf(@field(
@@ -1141,6 +1129,460 @@ pub fn NewClassWithInstanceType(
return definition;
}
+ const GetterNameFormatter = struct {
+ index: usize = 0,
+
+ pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ try writer.writeAll(std.mem.span(class_name_str));
+ try writer.writeAll("_get_");
+ const property_name = property_names[this.index];
+ try writer.writeAll(std.mem.span(property_name));
+ }
+ };
+
+ const SetterNameFormatter = struct {
+ index: usize = 0,
+
+ pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ try writer.writeAll(std.mem.span(class_name_str));
+ try writer.writeAll("_set_");
+ const property_name = property_names[this.index];
+ try writer.writeAll(std.mem.span(property_name));
+ }
+ };
+
+ const FunctionNameFormatter = struct {
+ index: usize = 0,
+
+ pub fn format(this: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ try writer.writeAll(std.mem.span(class_name_str));
+ try writer.writeAll("_fn_");
+ const property_name = function_names[this.index];
+ try writer.writeAll(std.mem.span(property_name));
+ }
+ };
+
+ const PropertyDeclaration = struct {
+ index: usize = 0,
+ pub fn format(this: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ const property = definition.staticValues[this.index];
+
+ if (property.getProperty != null) {
+ try writer.writeAll("static JSC_DECLARE_CUSTOM_GETTER(");
+ const getter_name = GetterNameFormatter{ .index = this.index };
+ try getter_name.format(fmt, opts, writer);
+ try writer.writeAll(");\n");
+ }
+
+ if (property.setProperty != null) {
+ try writer.writeAll("static JSC_DECLARE_CUSTOM_SETTER(");
+ const getter_name = SetterNameFormatter{ .index = this.index };
+ try getter_name.format(fmt, opts, writer);
+ try writer.writeAll(");\n");
+ }
+ }
+ };
+
+ const FunctionDeclaration = struct {
+ index: usize = 0,
+ pub fn format(this: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ const function = definition.staticFunctions[this.index];
+
+ if (function.callAsFunction != null) {
+ try writer.writeAll("static JSC_DECLARE_HOST_FUNCTION(");
+ const getter_name = FunctionNameFormatter{ .index = this.index };
+ try getter_name.format(fmt, opts, writer);
+ try writer.writeAll(");\n");
+ }
+ }
+ };
+
+ const PropertyDefinition = struct {
+ index: usize = 0,
+ pub fn format(this: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ const property = definition.staticValues[this.index];
+
+ if (property.getProperty != null) {
+ try writer.writeAll("static JSC_DEFINE_CUSTOM_GETTER(");
+ const getter_name = GetterNameFormatter{ .index = this.index };
+ try getter_name.format(fmt, opts, writer);
+ try writer.writeAll(", (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::PropertyName)) {\n");
+ try std.fmt.format(
+ writer,
+ \\ JSC::VM& vm = globalObject->vm();
+ \\ Bun::{[name]s}* thisObject = JSC::jsDynamicCast<Bun::{[name]s}*>(vm, JSValue::decode(thisValue));
+ \\ if (UNLIKELY(!thisObject)) {{
+ \\ return JSValue::encode(JSC::jsUndefined());
+ \\ }}
+ \\
+ \\ auto clientData = Bun::clientData(vm);
+ \\ auto scope = DECLARE_THROW_SCOPE(vm);
+ \\
+ ,
+ .{ .name = std.mem.span(class_name_str) },
+ );
+ if (ZigType == void) {
+ try std.fmt.format(
+ writer,
+ \\ JSC::EncodedJSValue result = Zig__{[getter]any}(globalObject);
+ ,
+ .{ .getter = getter_name },
+ );
+ } else {
+ try std.fmt.format(
+ writer,
+ \\ JSC::EncodedJSValue result = Zig__{[getter]any}(globalObject, thisObject->m_ptr);
+ ,
+ .{ .getter = getter_name },
+ );
+ }
+
+ try writer.writeAll(
+ \\ JSC::JSObject *obj = JSC::JSValue::decode(result).getObject();
+ \\
+ \\ if (UNLIKELY(obj != nullptr && obj->isErrorInstance())) {
+ \\ scope.throwException(globalObject, obj);
+ \\ return JSValue::encode(JSC::jsUndefined());
+ \\ }
+ \\
+ \\ scope.release();
+ \\
+ \\ return result;
+ );
+
+ try writer.writeAll("}\n");
+ }
+
+ if (property.setProperty != null) {
+ try writer.writeAll("JSC_DEFINE_CUSTOM_SETTER(");
+ const getter_name = SetterNameFormatter{ .index = this.index };
+ try getter_name.format(fmt, opts, writer);
+ try writer.writeAll(", (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue value, JSC::PropertyName)) {\n");
+ try std.fmt.format(writer,
+ \\ JSC::VM& vm = globalObject->vm();
+ \\ Bun::{[name]s}* thisObject = JSC::jsDynamicCast<Bun::{[name]s}*>(vm, JSValue::decode(thisValue));
+ \\ if (UNLIKELY(!thisObject)) {{
+ \\ return false;
+ \\ }}
+ \\
+ \\ auto clientData = Bun::clientData(vm);
+ \\ auto scope = DECLARE_THROW_SCOPE(vm);
+ \\
+ \\
+ , .{ .name = getter_name });
+ try writer.writeAll("};\n");
+ }
+ }
+ };
+
+ const PropertyDeclarationsFormatter = struct {
+ pub fn format(_: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ for (definition.staticValues[0 .. static_values_ptr.len - 1]) |_, i| {
+ const property = PropertyDeclaration{ .index = i };
+ try property.format(fmt, opts, writer);
+ }
+ }
+ };
+
+ const PropertyDefinitionsFormatter = struct {
+ pub fn format(_: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ if (static_values_ptr.len > 1) {
+ for (definition.staticValues[0 .. static_values_ptr.len - 1]) |_, i| {
+ const property = PropertyDefinition{ .index = i };
+ try property.format(fmt, opts, writer);
+ }
+ }
+ }
+ };
+
+ const FunctionDefinitionsFormatter = struct {
+ pub fn format(_: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ _ = fmt;
+ _ = writer;
+ _ = opts;
+ // for (static_properties[0 .. static_properties.len - 1]) |_, i| {
+ // const property = FunctionDefinition{ .index = i };
+ // try property.format(fmt, opts, writer);
+ // }
+ }
+ };
+
+ const FunctionDeclarationsFormatter = struct {
+ pub fn format(_: @This(), comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void {
+ _ = fmt;
+ _ = writer;
+ const definition = getDefinition();
+ if (static_functions__.len > 1) {
+ for (definition.staticFunctions[0 .. static_functions__.len - 1]) |_, i| {
+ const function = FunctionDeclaration{ .index = i };
+ try function.format(fmt, opts, writer);
+ }
+ }
+ }
+ };
+
+ pub fn @"generateC++Header"(writer: anytype) !void {
+ const header_file =
+ \\// AUTO-GENERATED FILE
+ \\#pragma once
+ \\
+ \\#include "BunBuiltinNames.h"
+ \\#include "BunClientData.h"
+ \\#include "root.h"
+ \\
+ \\
+ \\namespace Bun {{
+ \\
+ \\using namespace JSC;
+ \\using namespace Zig;
+ \\
+ \\class {[name]s} : public JSNonFinalObject {{
+ \\ using Base = JSNonFinalObject;
+ \\
+ \\public:
+ \\ {[name]s}(JSC::VM& vm, Structure* structure) : Base(vm, structure) {{}}
+ \\
+ \\
+ \\ DECLARE_INFO;
+ \\
+ \\ static constexpr unsigned StructureFlags = Base::StructureFlags;
+ \\ template<typename CellType, SubspaceAccess> static GCClient::IsoSubspace* subspaceFor(VM& vm)
+ \\ {{
+ \\ return &vm.cellSpace();
+ \\ }}
+ \\ 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());
+ \\ }}
+ \\
+ \\ static {[name]s}* create(JSC::VM& vm, JSC::Structure* structure)
+ \\ {{
+ \\ {[name]s}* accessor = new (NotNull, JSC::allocateCell<{[name]s}>(vm)) {[name]s}(vm, structure);
+ \\ accessor->finishCreation(vm);
+ \\ return accessor;
+ \\ }}
+ \\
+ \\ void finishCreation(JSC::VM& vm);
+ \\
+ \\}};
+ \\
+ \\}} // namespace Bun
+ \\
+ ;
+ _ = writer;
+ _ = header_file;
+ const Opts = struct { name: string };
+ try writer.print(header_file, Opts{
+ .name = std.mem.span(name),
+ });
+ }
+
+ const LookupTableFormatter = struct {
+ // example:
+ //
+ // /* Source for IntlLocalePrototype.lut.h
+ // @begin localePrototypeTable
+ // maximize intlLocalePrototypeFuncMaximize DontEnum|Function 0
+ // minimize intlLocalePrototypeFuncMinimize DontEnum|Function 0
+ // toString intlLocalePrototypeFuncToString DontEnum|Function 0
+ // baseName intlLocalePrototypeGetterBaseName DontEnum|ReadOnly|CustomAccessor
+ // calendar intlLocalePrototypeGetterCalendar DontEnum|ReadOnly|CustomAccessor
+ // calendars intlLocalePrototypeGetterCalendars DontEnum|ReadOnly|CustomAccessor
+ // caseFirst intlLocalePrototypeGetterCaseFirst DontEnum|ReadOnly|CustomAccessor
+ // collation intlLocalePrototypeGetterCollation DontEnum|ReadOnly|CustomAccessor
+ // collations intlLocalePrototypeGetterCollations DontEnum|ReadOnly|CustomAccessor
+ // hourCycle intlLocalePrototypeGetterHourCycle DontEnum|ReadOnly|CustomAccessor
+ // hourCycles intlLocalePrototypeGetterHourCycles DontEnum|ReadOnly|CustomAccessor
+ // numeric intlLocalePrototypeGetterNumeric DontEnum|ReadOnly|CustomAccessor
+ // numberingSystem intlLocalePrototypeGetterNumberingSystem DontEnum|ReadOnly|CustomAccessor
+ // numberingSystems intlLocalePrototypeGetterNumberingSystems DontEnum|ReadOnly|CustomAccessor
+ // language intlLocalePrototypeGetterLanguage DontEnum|ReadOnly|CustomAccessor
+ // script intlLocalePrototypeGetterScript DontEnum|ReadOnly|CustomAccessor
+ // region intlLocalePrototypeGetterRegion DontEnum|ReadOnly|CustomAccessor
+ // timeZones intlLocalePrototypeGetterTimeZones DontEnum|ReadOnly|CustomAccessor
+ // textInfo intlLocalePrototypeGetterTextInfo DontEnum|ReadOnly|CustomAccessor
+ // weekInfo intlLocalePrototypeGetterWeekInfo DontEnum|ReadOnly|CustomAccessor
+ // @end
+ // */
+ pub fn format(_: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ const definition = getDefinition();
+ try writer.writeAll("/* Source for ");
+ try writer.writeAll(std.mem.span(definition.className));
+ try writer.writeAll(".lut.h\n");
+ try writer.writeAll("@begin ");
+ try writer.writeAll(std.mem.span(definition.className));
+ try writer.writeAll("HashTableValues \n");
+ var middle_padding: usize = 0;
+ if (property_names.len > 0) {
+ for (property_names) |prop| {
+ middle_padding = @maximum(prop.len, middle_padding);
+ }
+ }
+ if (function_names.len > 0) {
+ for (function_names[0..function_names.len]) |_name| {
+ middle_padding = @maximum(std.mem.span(_name).len, middle_padding);
+ }
+ }
+
+ if (property_names.len > 0) {
+ comptime var i: usize = 0;
+ inline while (i < property_names.len) : (i += 1) {
+ try writer.writeAll(" ");
+ const name_ = property_names[i];
+ try writer.writeAll(name_);
+ try writer.writeAll(" ");
+ var k: usize = 0;
+ while (k < middle_padding - name_.len) : (k += 1) {
+ try writer.writeAll(" ");
+ }
+
+ try writer.print("{any} ", .{GetterNameFormatter{ .index = i }});
+
+ k = 0;
+
+ while (k < middle_padding - name_.len) : (k += 1) {
+ try writer.writeAll(" ");
+ }
+
+ try writer.writeAll("CustomAccessor");
+ if (options.read_only or @hasField(@TypeOf(@field(properties, property_names[i])), "ro")) {
+ try writer.writeAll("|ReadOnly");
+ }
+
+ if (@hasField(@TypeOf(@field(properties, property_names[i])), "enumerable") and !@field(properties, property_names[i])) {
+ try writer.writeAll("|DontEnum");
+ }
+
+ try writer.writeAll("\n");
+ }
+ }
+ if (function_names.len > 0) {
+ comptime var i: usize = 0;
+ inline while (i < function_names.len) : (i += 1) {
+ try writer.writeAll(" ");
+ const name_ = function_names[i];
+ try writer.writeAll(name_);
+ try writer.writeAll(" ");
+ var k: usize = 0;
+ while (k < middle_padding - name_.len) : (k += 1) {
+ try writer.writeAll(" ");
+ }
+
+ try writer.print("{any} ", .{FunctionNameFormatter{ .index = i }});
+ k = 0;
+
+ while (k < middle_padding - name_.len) : (k += 1) {
+ try writer.writeAll(" ");
+ }
+ var read_only_ = false;
+ if (options.read_only or @hasField(@TypeOf(comptime @field(staticFunctions, function_names[i])), "ro")) {
+ read_only_ = true;
+ try writer.writeAll("ReadOnly");
+ }
+
+ if (comptime std.meta.trait.isContainer(
+ @TypeOf(comptime @field(staticFunctions, function_names[i])),
+ ) and
+ @hasField(@TypeOf(comptime @field(
+ staticFunctions,
+ function_names[i],
+ )), "enumerable") and !@field(staticFunctions, function_names[i]).enumerable) {
+ if (read_only_) {
+ try writer.writeAll("|");
+ }
+ try writer.writeAll("DontEnum");
+ }
+
+ try writer.writeAll("Function 1");
+
+ try writer.writeAll("\n");
+ }
+ }
+
+ try writer.writeAll("@end\n*/\n");
+ }
+ };
+
+ pub fn @"generateC++Class"(writer: anytype) !void {
+ const implementation_file =
+ \\// AUTO-GENERATED FILE
+ \\
+ \\#include "{[name]s}.generated.h"
+ \\#include "{[name]s}.lut.h"
+ \\
+ \\namespace Bun {{
+ \\
+ \\{[lut]any}
+ \\
+ \\using JSGlobalObject = JSC::JSGlobalObject;
+ \\using Exception = JSC::Exception;
+ \\using JSValue = JSC::JSValue;
+ \\using JSString = JSC::JSString;
+ \\using JSModuleLoader = JSC::JSModuleLoader;
+ \\using JSModuleRecord = JSC::JSModuleRecord;
+ \\using Identifier = JSC::Identifier;
+ \\using SourceOrigin = JSC::SourceOrigin;
+ \\using JSObject = JSC::JSObject;
+ \\using JSNonFinalObject = JSC::JSNonFinalObject;
+ \\namespace JSCastingHelpers = JSC::JSCastingHelpers;
+ \\
+ \\#pragma mark - Function Declarations
+ \\
+ \\{[function_declarations]any}
+ \\
+ \\#pragma mark - Property Declarations
+ \\
+ \\{[property_declarations]any}
+ \\
+ \\#pragma mark - Function Definitions
+ \\
+ \\{[function_definitions]any}
+ \\
+ \\#pragma mark - Property Definitions
+ \\
+ \\{[property_definitions]any}
+ \\
+ \\const JSC::ClassInfo {[name]s}::s_info = {{ "{[name]s}", &Base::s_info, &{[name]s}HashTableValues, nullptr, CREATE_METHOD_TABLE([name]s) }};
+ \\
+ \\ void {[name]s}::finishCreation(JSC::VM& vm) {{
+ \\ Base::finishCreation(vm);
+ \\ auto clientData = Bun::clientData(vm);
+ \\ JSC::JSGlobalObject *globalThis = globalObject();
+ \\
+ \\
+ \\#pragma mark - Property Initializers
+ \\
+ \\{[property_initializers]any}
+ \\
+ \\#pragma mark - Function Initializers
+ \\
+ \\{[function_initializers]any}
+ \\
+ \\ }}
+ \\
+ \\}} // namespace Bun
+ \\
+ ;
+
+ try writer.print(implementation_file, .{
+ .name = std.mem.span(class_name_str),
+ .function_initializers = @as(string, ""),
+ .property_initializers = @as(string, ""),
+ .function_declarations = FunctionDeclarationsFormatter{},
+ .property_declarations = FunctionDeclarationsFormatter{},
+ .function_definitions = FunctionDefinitionsFormatter{},
+ .property_definitions = PropertyDefinitionsFormatter{},
+ .lut = LookupTableFormatter{},
+ });
+ }
+
// This should only be run at comptime
pub fn typescriptModuleDeclaration() d.ts.module {
comptime var class = options.ts.module;
@@ -1325,8 +1767,6 @@ pub fn NewClassWithInstanceType(
_: js.JSObjectRef,
props: js.JSPropertyNameAccumulatorRef,
) callconv(.C) void {
- if (comptime JSC.is_bindgen)
- unreachable;
if (comptime property_name_refs.len > 0) {
comptime var i: usize = 0;
if (!property_name_refs_set) {
@@ -1480,7 +1920,7 @@ pub fn NewClassWithInstanceType(
return comptime class;
}
- const static_properties = brk: {
+ const static_properties: [property_names.len + 1]js.JSStaticValue = brk: {
var props: [property_names.len + 1]js.JSStaticValue = undefined;
std.mem.set(
js.JSStaticValue,
@@ -1660,7 +2100,7 @@ pub fn NewClassWithInstanceType(
}
const base_def_ = generateDef(JSC.C.JSClassDefinition);
- const static_functions__ = generateDef([function_name_literals.len + 1]js.JSStaticFunction);
+ const static_functions__: [function_name_literals.len + 1]js.JSStaticFunction = generateDef([function_name_literals.len + 1]js.JSStaticFunction);
const static_functions_ptr = &static_functions__;
const static_values_ptr = &static_properties;
const class_name_str: stringZ = options.name;
@@ -1709,9 +2149,6 @@ pub fn JSError(
ctx: js.JSContextRef,
exception: ExceptionValueRef,
) void {
- if (comptime JSC.is_bindgen)
- unreachable;
-
var error_args: [1]js.JSValueRef = undefined;
@setCold(true);
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index eebeae8e9..ca8c72f75 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -161,8 +161,6 @@ pub fn ConcurrentPromiseTask(comptime Context: type) type {
}
pub fn runFromJS(this: This) void {
- if (comptime JSC.is_bindgen)
- unreachable;
var promise_value = this.promise;
var promise = promise_value.asInternalPromise() orelse {
if (comptime @hasDecl(Context, "deinit")) {
@@ -492,6 +490,17 @@ pub const VirtualMachine = struct {
source_mappings: SavedSourceMap = undefined,
response_objects_pool: ?*Response.Pool = null,
+
+ rare_data: ?*JSC.RareData = null,
+
+ pub inline fn rareData(this: *VirtualMachine) *JSC.RareData {
+ return this.rare_data orelse brk: {
+ this.rare_data = this.allocator.create(JSC.RareData) catch unreachable;
+ this.rare_data.?.* = .{};
+ break :brk this.rare_data.?;
+ };
+ }
+
pub inline fn eventLoop(this: *VirtualMachine) *EventLoop {
return this.event_loop;
}
diff --git a/src/javascript/jsc/rare_data.zig b/src/javascript/jsc/rare_data.zig
new file mode 100644
index 000000000..72bf45fbd
--- /dev/null
+++ b/src/javascript/jsc/rare_data.zig
@@ -0,0 +1,3 @@
+const EditorContext = @import("../../open.zig").EditorContext;
+
+editor_context: EditorContext = EditorContext{},