Implement error page for HTTP server

This commit is contained in:
Jarred Sumner
2022-03-24 19:08:20 -07:00
parent 92a46c292f
commit 3434b9ecf3
14 changed files with 894 additions and 171 deletions

View File

@@ -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,

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -0,0 +1,3 @@
const EditorContext = @import("../../open.zig").EditorContext;
editor_context: EditorContext = EditorContext{},