aboutsummaryrefslogtreecommitdiff
path: root/src/javascript/jsc/javascript.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/javascript/jsc/javascript.zig')
-rw-r--r--src/javascript/jsc/javascript.zig516
1 files changed, 492 insertions, 24 deletions
diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig
index e63cee40f..50c40e746 100644
--- a/src/javascript/jsc/javascript.zig
+++ b/src/javascript/jsc/javascript.zig
@@ -11,7 +11,7 @@ const Bundler = @import("../../bundler.zig").ServeBundler;
const js_printer = @import("../../js_printer.zig");
const hash_map = @import("../../hash_map.zig");
const http = @import("../../http.zig");
-
+const ImportKind = ast.ImportKind;
usingnamespace @import("./node_env_buf_map.zig");
usingnamespace @import("./base.zig");
usingnamespace @import("./webcore/response.zig");
@@ -26,8 +26,12 @@ pub const GlobalClasses = [_]type{
Response.Class,
Headers.Class,
EventListenerMixin.addEventListener(VirtualMachine),
+ BuildError.Class,
+ ResolveError.Class,
};
+pub const LazyClasses = [_]type{};
+
pub const Module = struct {
reload_pending: bool = false,
};
@@ -106,7 +110,12 @@ pub const VirtualMachine = struct {
threadlocal var source_code_printer: js_printer.BufferPrinter = undefined;
threadlocal var source_code_printer_loaded: bool = false;
- inline fn _fetch(global: *JSGlobalObject, specifier: string, source: string) !ResolvedSource {
+ inline fn _fetch(
+ global: *JSGlobalObject,
+ specifier: string,
+ source: string,
+ log: *logger.Log,
+ ) !ResolvedSource {
std.debug.assert(VirtualMachine.vm_loaded);
std.debug.assert(VirtualMachine.vm.global == global);
@@ -158,6 +167,10 @@ pub const VirtualMachine = struct {
}
}
+ var old = vm.bundler.log;
+ vm.bundler.log = log;
+ defer vm.bundler.log = old;
+
var parse_result = vm.bundler.parse(
vm.bundler.allocator,
path,
@@ -202,7 +215,7 @@ pub const VirtualMachine = struct {
return ResolvedSource{
.source_code = ZigString.init(vm.allocator.dupe(u8, source_code_printer.ctx.written) catch unreachable),
.specifier = ZigString.init(specifier),
- .source_url = ZigString.init(path.pretty),
+ .source_url = ZigString.init(path.text),
.hash = 0,
.bytecodecache_fd = 0,
};
@@ -211,7 +224,7 @@ pub const VirtualMachine = struct {
return ResolvedSource{
.source_code = ZigString.init(try strings.quotedAlloc(VirtualMachine.vm.allocator, path.pretty)),
.specifier = ZigString.init(path.text),
- .source_url = ZigString.init(path.pretty),
+ .source_url = ZigString.init(path.text),
.hash = 0,
.bytecodecache_fd = 0,
};
@@ -295,15 +308,32 @@ pub const VirtualMachine = struct {
return ErrorableZigString.ok(ZigString.init(result));
}
- pub fn fetch(global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) ErrorableResolvedSource {
+ pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: ZigString, source: ZigString) callconv(.C) void {
+ var log = logger.Log.init(vm.bundler.allocator);
const result = _fetch(global, specifier.slice(), source.slice()) catch |err| {
- return ErrorableResolvedSource.errFmt(err, "{s}: \"{s}\"", .{
- @errorName(err),
- specifier.slice(),
- });
+ switch (err) {
+ error.ParserError => {
+ std.debug.assert(log.msgs.items.len > 0);
+
+ switch (log.msgs.items.len) {
+ 1 => {
+ return ErrorableResolvedSource.err(error.ParserError, BuildError.create(vm.bundler.allocator, &log.msgs.items[0]));
+ },
+ else => {
+
+ },
+ }
+ },
+ else => {
+ ret.* = ErrorableResolvedSource.errFmt(err, "{s}: \"{s}\"", .{
+ @errorName(err),
+ specifier.slice(),
+ });
+ },
+ }
};
- return ErrorableResolvedSource.ok(result);
+ ret.* = ErrorableResolvedSource.ok(result);
}
pub fn loadEntryPoint(this: *VirtualMachine, entry_point: string) !void {
@@ -318,15 +348,179 @@ pub const VirtualMachine = struct {
}
if (promise.status(this.global.vm()) == JSPromise.Status.Rejected) {
- var exception = promise.result(this.global.vm()).toZigException(this.global);
- Output.prettyErrorln("<r><red>{s}<r><d>:<r> <b>{s}<r>\n<blue>{s}<r>:{d}:{d}\n{s}", .{
- exception.name.slice(),
- exception.message.slice(),
- exception.sourceURL.slice(),
- exception.line,
- exception.column,
- exception.stack.slice(),
- });
+ var exception_holder = ZigException.Holder.init();
+ var exception = exception_holder.zigException();
+ promise.result(this.global.vm()).toZigException(vm.global, exception);
+ var stderr: std.fs.File = Output.errorStream();
+ var buffered = std.io.bufferedWriter(stderr.writer());
+ var writer = buffered.writer();
+ defer buffered.flush() catch unreachable;
+ // We are going to print the stack trace backwards
+ const stack = exception.stack.frames();
+ if (stack.len > 0) {
+ var i = @intCast(i16, stack.len - 1);
+
+ var func_name_pad: usize = 0;
+ while (i >= 0) : (i -= 1) {
+ const frame = stack[@intCast(usize, i)];
+ func_name_pad = std.math.max(func_name_pad, std.fmt.count("{any}", .{
+ frame.nameFormatter(true),
+ }));
+ }
+
+ i = @intCast(i16, stack.len - 1);
+
+ while (i >= 0) : (i -= 1) {
+ const frame = stack[@intCast(usize, i)];
+ const file = frame.source_url.slice();
+ const func = frame.function_name.slice();
+
+ try writer.print(" {any}", .{frame.sourceURLFormatter(true)});
+ try writer.writeAll(" in ");
+ try writer.print(" {any}\n", .{frame.nameFormatter(true)});
+
+ // if (!frame.position.isInvalid()) {
+ // if (func.len > 0) {
+ // writer.print(
+ // comptime Output.prettyFmt("<r><d>{s}<r> {s}{s} - {s}:{d}:{d}\n", true),
+ // .{
+ // if (i > 1) "↓" else "↳",
+ // frame.code_type.ansiColor(),
+ // func,
+ // file,
+ // frame.position.line,
+ // frame.position.column_start,
+ // },
+ // ) catch unreachable;
+ // } else {
+ // writer.print(comptime Output.prettyFmt("<r><d>{s}<r> {u} - {s}{s}:{d}:{d}\n", true), .{
+ // if (i > 1) "↓" else "↳",
+ // frame.code_type.emoji(),
+
+ // frame.code_type.ansiColor(),
+ // file,
+ // frame.position.line,
+ // frame.position.column_start,
+ // }) catch unreachable;
+ // }
+ // } else {
+ // if (func.len > 0) {
+ // writer.print(
+ // comptime Output.prettyFmt("<r><d>{s}<r> {s}{s} - {s}\n", true),
+ // .{
+ // if (i > 1) "↓" else "↳",
+ // frame.code_type.ansiColor(),
+ // func,
+ // file,
+ // },
+ // ) catch unreachable;
+ // } else {
+ // writer.print(
+ // comptime Output.prettyFmt("<r><d>{s}<r> {u} - {s}{s}\n", true),
+ // .{
+ // if (i > 1) "↓" else "↳",
+ // frame.code_type.emoji(),
+ // frame.code_type.ansiColor(),
+ // file,
+ // },
+ // ) catch unreachable;
+ // }
+ // }
+ }
+ }
+
+ var line_numbers = exception.stack.source_lines_numbers[0..exception.stack.source_lines_len];
+ var max_line: i32 = -1;
+ for (line_numbers) |line| max_line = std.math.max(max_line, line);
+ const max_line_number_pad = std.fmt.count("{d}", .{max_line});
+
+ var source_lines = exception.stack.sourceLineIterator();
+ var last_pad: u64 = 0;
+ while (source_lines.untilLast()) |source| {
+ const int_size = std.fmt.count("{d}", .{source.line});
+ const pad = max_line_number_pad - int_size;
+ last_pad = pad;
+ writer.writeByteNTimes(' ', pad) catch unreachable;
+ writer.print(
+ comptime Output.prettyFmt("<r><d>{d} | <r>{s}\n", true),
+ .{
+ source.line,
+ std.mem.trim(u8, source.text, "\n"),
+ },
+ ) catch unreachable;
+ }
+
+ const name = exception.name.slice();
+ const message = exception.message.slice();
+ var did_print_name = false;
+ if (source_lines.next()) |source| {
+ const int_size = std.fmt.count("{d}", .{source.line});
+ const pad = max_line_number_pad - int_size;
+ writer.writeByteNTimes(' ', pad) catch unreachable;
+
+ std.debug.assert(!stack[0].position.isInvalid());
+ var remainder = std.mem.trim(u8, source.text, "\n");
+ const prefix = remainder[0..@intCast(usize, stack[0].position.column_start)];
+ const underline = remainder[@intCast(usize, stack[0].position.column_start)..@intCast(usize, stack[0].position.column_stop)];
+ const suffix = remainder[@intCast(usize, stack[0].position.column_stop)..];
+
+ writer.print(
+ comptime Output.prettyFmt("<r><d>{d} |<r> {s}<red>{s}<r>{s}<r>\n<r>", true),
+ .{
+ source.line,
+ prefix,
+ underline,
+ suffix,
+ },
+ ) catch unreachable;
+ var first_non_whitespace = @intCast(u32, stack[0].position.column_start);
+ while (first_non_whitespace < source.text.len and source.text[first_non_whitespace] == ' ') {
+ first_non_whitespace += 1;
+ }
+ std.debug.assert(stack.len > 0);
+ const indent = @intCast(usize, pad) + " | ".len + first_non_whitespace + 1;
+
+ writer.writeByteNTimes(' ', indent) catch unreachable;
+ writer.print(comptime Output.prettyFmt(
+ "<red><b>^<r>\n",
+ true,
+ ), .{}) catch unreachable;
+
+ if (name.len > 0 and message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><red><b>{s}<r><d>:<r> <b>{s}<r>\n", true), .{
+ name,
+ message,
+ }) catch unreachable;
+ } else if (name.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{s}<r>\n", true), .{name}) catch unreachable;
+ } else if (message.len > 0) {
+ writer.print(comptime Output.prettyFmt(" <r><b>{s}<r>\n", true), .{message}) catch unreachable;
+ }
+
+ did_print_name = true;
+ }
+
+ if (!did_print_name) {
+ if (name.len > 0 and message.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r><red><b>{s}<r><d>:<r> <b>{s}<r>\n", true), .{
+ name,
+ message,
+ }) catch unreachable;
+ } else if (name.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r><b>{s}<r>\n", true), .{name}) catch unreachable;
+ } else if (message.len > 0) {
+ writer.print(comptime Output.prettyFmt("<r><b>{s}<r>\n", true), .{name}) catch unreachable;
+ }
+ }
+
+ // Output.prettyErrorln("<r><red>{s}<r><d>:<r> <b>{s}<r>\n<blue>{s}<r>:{d}:{d}\n{s}", .{
+ // exception.name.slice(),
+ // exception.message.slice(),
+ // exception.sourceURL.slice(),
+ // exception.line,
+ // exception.column,
+ // exception.stack.slice(),
+ // });
}
}
};
@@ -411,11 +605,7 @@ pub const EventListenerMixin = struct {
var fetch_args: [1]js.JSObjectRef = undefined;
for (listeners.items) |listener| {
- fetch_args[0] = js.JSObjectMake(
- vm.ctx,
- FetchEvent.Class.get().*,
- fetch_event,
- );
+ fetch_args[0] = FetchEvent.Class.make(vm.global, fetch_event);
_ = js.JSObjectCallAsFunction(
vm.ctx,
@@ -510,3 +700,281 @@ pub const EventListenerMixin = struct {
);
}
};
+
+pub const ResolveError = struct {
+ msg: logger.Msg,
+ allocator: *std.mem.Allocator,
+ referrer: ?Fs.Path = null,
+
+ pub const Class = NewClass(
+ ResolveError,
+ .{
+ .name = "ResolveError",
+ .read_only = true,
+ },
+ .{
+ .@"referrer" = .{
+ .@"get" = getReferrer,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"message" = .{
+ .@"get" = getMessage,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"name" = .{
+ .@"get" = getName,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"specifier" = .{
+ .@"get" = getSpecifier,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"importKind" = .{
+ .@"get" = getImportKind,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ .@"position" = .{
+ .@"get" = getPosition,
+ .ro = true,
+ .ts = d.ts{ .@"return" = "string" },
+ },
+ },
+ .{},
+ );
+
+ pub fn create(
+ msg: logger.Msg,
+ allocator: *std.mem.Allocator,
+ ) js.JSObjectRef {
+ var resolve_error = allocator.create(ResolveError) catch unreachable;
+ resolve_error.* = ResolveError{
+ .msg = msg,
+ .allocator = allocator,
+ };
+
+ return Class.make(VirtualMachine.vm.global, resolve_error);
+ }
+
+ pub fn getPosition(
+ this: *ResolveError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return BuildError.generatePositionObject(this.msg, ctx, exception);
+ }
+
+ pub fn getMessage(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.data.text).toValue(VirtualMachine.vm.global);
+ }
+
+ pub fn getSpecifier(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.metadata.Resolve.specifier.slice(this.msg.data.text)).toValue(VirtualMachine.vm.global);
+ }
+
+ pub fn getImportKind(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(@tagName(this.msg.metadata.Resolve.import_kind)).toValue(VirtualMachine.vm.global);
+ }
+
+ pub fn getReferrer(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ if (this.referrer) |referrer| {
+ return ZigString.init(referrer.text).toValue(VirtualMachine.vm.global);
+ } else {
+ return js.JSValueMakeNull(ctx);
+ }
+ }
+
+ const BuildErrorName = "ResolveError";
+ pub fn getName(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(BuildErrorName).toValue(VirtualMachine.vm.global);
+ }
+};
+
+pub const BuildError = struct {
+ msg: logger.Msg,
+ // resolve_result: resolver.Result,
+ allocator: *std.mem.Allocator,
+
+ pub const Class = NewClass(
+ BuildError,
+ .{
+ .name = "BuildError",
+ .read_only = true,
+ },
+ .{},
+ .{
+ .@"message" = .{
+ .@"get" = getMessage,
+ .ro = true,
+ },
+ .@"name" = .{
+ .@"get" = getName,
+ .ro = true,
+ },
+ // This is called "position" instead of "location" because "location" may be confused with Location.
+ .@"position" = .{
+ .@"get" = getPosition,
+ .ro = true,
+ },
+ },
+ );
+
+ pub fn create(
+ allocator: *std.mem.Allocator,
+ msg: *const logger.Msg,
+ // resolve_result: *const resolver.Result,
+ ) js.JSObjectRef {
+ var build_error = allocator.create(BuildError) catch unreachable;
+ build_error.* = BuildError{
+ .msg = msg.*,
+ // .resolve_result = resolve_result.*,
+ .allocator = allocator,
+ };
+
+ return Class.make(VirtualMachine.vm.global, build_error);
+ }
+
+ pub fn getPosition(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return generatePositionObject(this.msg, ctx, exception);
+ }
+
+ pub const PositionProperties = struct {
+ const _file = ZigString.init("file");
+ var file_ptr: js.JSStringRef = null;
+ pub fn file() js.JSStringRef {
+ if (file_ptr == null) {
+ file_ptr = _file.toJSStringRef();
+ }
+ return file_ptr.?;
+ }
+ const _namespace = ZigString.init("namespace");
+ var namespace_ptr: js.JSStringRef = null;
+ pub fn namespace() js.JSStringRef {
+ if (namespace_ptr == null) {
+ namespace_ptr = _namespace.toJSStringRef();
+ }
+ return namespace_ptr.?;
+ }
+ const _line = ZigString.init("line");
+ var line_ptr: js.JSStringRef = null;
+ pub fn line() js.JSStringRef {
+ if (line_ptr == null) {
+ line_ptr = _line.toJSStringRef();
+ }
+ return line_ptr.?;
+ }
+ const _column = ZigString.init("column");
+ var column_ptr: js.JSStringRef = null;
+ pub fn column() js.JSStringRef {
+ if (column_ptr == null) {
+ column_ptr = _column.toJSStringRef();
+ }
+ return column_ptr.?;
+ }
+ const _length = ZigString.init("length");
+ var length_ptr: js.JSStringRef = null;
+ pub fn length() js.JSStringRef {
+ if (length_ptr == null) {
+ length_ptr = _length.toJSStringRef();
+ }
+ return length_ptr.?;
+ }
+ const _lineText = ZigString.init("lineText");
+ var lineText_ptr: js.JSStringRef = null;
+ pub fn lineText() js.JSStringRef {
+ if (lineText_ptr == null) {
+ lineText_ptr = _lineText.toJSStringRef();
+ }
+ return lineText_ptr.?;
+ }
+ const _offset = ZigString.init("offset");
+ var offset_ptr: js.JSStringRef = null;
+ pub fn offset() js.JSStringRef {
+ if (offset_ptr == null) {
+ offset_ptr = _offset.toJSStringRef();
+ }
+ return offset_ptr.?;
+ }
+ };
+
+ pub fn generatePositionObject(msg: logger.Msg, ctx: js.JSContextRef, exception: ExceptionValueRef) js.JSValue {
+ if (msg.data.location) |location| {
+ const ref = js.JSObjectMake(ctx, null, null);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.lineText(), ZigString.init(location.line_text orelse "").toJSStringRef(), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.file(), ZigString.init(location.file).toJSStringRef(), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.namespace(), ZigString.init(location.namespace).toJSStringRef(), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.line(), js.JSValueMakeNumber(ctx, location.line), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.column(), js.JSValueMakeNumber(ctx, location.column), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.length(), js.JSValueMakeNumber(ctx, location.length), 0, exception);
+ js.JSObjectSetProperty(ctx, ref, PositionProperties.offset(), js.JSValueMakeNumber(ctx, location.offset), 0, exception);
+ return ref;
+ }
+
+ return js.JSValueMakeNull(ctx);
+ }
+
+ pub fn getMessage(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(this.msg.data.text).toValue(VirtualMachine.vm.global);
+ }
+
+ const BuildErrorName = "BuildError";
+ pub fn getName(
+ this: *BuildError,
+ ctx: js.JSContextRef,
+ thisObject: js.JSObjectRef,
+ prop: js.JSStringRef,
+ exception: js.ExceptionRef,
+ ) js.JSValueRef {
+ return ZigString.init(BuildErrorName).toValue(VirtualMachine.vm.global);
+ }
+};
+
+pub const JSPrivateDataTag = JSPrivateDataPtr.Tag;