diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bun.js/api/ffi.zig | 6 | ||||
-rw-r--r-- | src/bun.js/api/transpiler.zig | 26 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 196 | ||||
-rw-r--r-- | src/bun.js/bindings/exports.zig | 14 | ||||
-rw-r--r-- | src/js_ast.zig | 6 |
5 files changed, 92 insertions, 156 deletions
diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index afe442096..59d682d3b 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -561,7 +561,7 @@ pub const FFI = struct { var symbols_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, - .name_encoding = .utf8, + .include_value = true, }).init(global.ref(), object.asObjectRef()); defer symbols_iter.deinit(); @@ -572,14 +572,14 @@ pub const FFI = struct { const value = symbols_iter.value; if (value.isEmptyOrUndefinedOrNull()) { - return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Expected an object for key \"{s}\"", .{prop}, global.ref()); + return JSC.toTypeError(JSC.Node.ErrorCode.ERR_INVALID_ARG_VALUE, "Expected an object for key \"{any}\"", .{prop}, global.ref()); } var function: Function = .{}; if (try generateSymbolForFunction(global, allocator, value, &function)) |val| { return val; } - function.base_name = try allocator.dupeZ(u8, prop); + function.base_name = try prop.toOwnedSliceZ(allocator); symbols.putAssumeCapacity(std.mem.span(function.base_name.?), function); } diff --git a/src/bun.js/api/transpiler.zig b/src/bun.js/api/transpiler.zig index a21f40e2e..8d6d2c141 100644 --- a/src/bun.js/api/transpiler.zig +++ b/src/bun.js/api/transpiler.zig @@ -364,8 +364,8 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo } var define_iter = JSC.JSPropertyIterator(.{ - .skip_empty_name = false, - .name_encoding = .utf8, + .skip_empty_name = true, + .include_value = true, }).init(globalThis.ref(), define.asObjectRef()); defer define_iter.deinit(); @@ -385,7 +385,7 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo return transpiler; } - names[define_iter.i] = allocator.dupe(u8, prop) catch unreachable; + names[define_iter.i] = prop.toOwnedSlice(allocator) catch unreachable; var val = JSC.ZigString.init(""); property_value.toZigString(&val, globalThis); if (val.len == 0) { @@ -500,6 +500,10 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo } transpiler.runtime.allow_runtime = false; + transpiler.runtime.dynamic_require = switch (transpiler.transform.platform orelse .browser) { + .bun, .bun_macro => true, + else => false, + }; if (object.getIfPropertyExists(globalThis, "macro")) |macros| { macros: { @@ -639,28 +643,32 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, - .name_encoding = .utf8, .include_value = true, - .override_writing_cstring = true, - }).initCStringBuffer(globalThis.ref(), replace.asObjectRef(), bun.default_allocator); + }).init(globalThis, replace.asObjectRef()); if (iter.len > 0) { - errdefer iter.deinit(bun.default_allocator); + errdefer iter.deinit(); try replacements.ensureUnusedCapacity(bun.default_allocator, iter.len); // We cannot set the exception before `try` because it could be // a double free with the `errdefer`. defer if (exception.* != null) { - iter.deinit(bun.default_allocator); + iter.deinit(); + for (replacements.keys()) |key| { + bun.default_allocator.free(bun.constStrToU8(key)); + } replacements.clearAndFree(bun.default_allocator); }; - while (iter.next()) |key| { + while (iter.next()) |key_| { const value = iter.value; if (value.isEmpty()) continue; + var key = try key_.toOwnedSlice(bun.default_allocator); + if (!JSLexer.isIdentifier(key)) { JSC.throwInvalidArguments("\"{s}\" is not a valid ECMAScript identifier", .{key}, ctx, exception); + bun.default_allocator.free(key); return transpiler; } diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index e4ccb379d..9f7771081 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -101,6 +101,33 @@ pub const ZigString = extern struct { return this; } + pub fn toOwnedSlice(this: ZigString, allocator: std.mem.Allocator) ![]u8 { + return try std.fmt.allocPrint(allocator, "{any}", .{this}); + } + + pub fn toOwnedSliceZ(this: ZigString, allocator: std.mem.Allocator) ![:0]u8 { + return try std.fmt.allocPrintZ(allocator, "{any}", .{this}); + } + + pub fn trunc(this: ZigString, len: usize) ZigString { + return .{ .ptr = this.ptr, .len = @minimum(len, this.len) }; + } + + pub fn eqlComptime(this: ZigString, comptime other: []const u8) bool { + if (this.len != other.len) + return false; + + if (this.is16Bit()) { + return strings.eqlComptimeUTF16(this.utf16SliceAligned(), other); + } + + if (comptime strings.isAllASCIISimple(other)) { + return strings.eqlComptimeIgnoreLen(this.slice(), other); + } + + @compileError("Not implemented yet for latin1"); + } + pub const shim = Shimmer("", "ZigString", @This()); pub const Slice = struct { @@ -1455,6 +1482,19 @@ pub const SourceCode = extern struct { pub const Thenables = opaque {}; +pub const StrongValue = opaque { + pub const shim = Shimmer("JSC", "JSFunction", @This()); + + const cppFn = shim.cppFn; + pub const include = "JavaScriptCore/JSFunction.h"; + pub const name = "JSC::JSFunction"; + pub const namespace = "JSC"; + + pub fn get(this: *StrongValue) JSValue { + return cppFn("get", .{this}); + } +}; + pub const JSFunction = extern struct { pub const shim = Shimmer("JSC", "JSFunction", @This()); bytes: shim.Bytes, @@ -3667,30 +3707,16 @@ pub fn Thenable(comptime Then: type, comptime onResolve: fn (*Then, globalThis: pub const JSPropertyIteratorOptions = struct { skip_empty_name: bool, - name_encoding: NameEncoding, include_value: bool, - /// Overrides the setup for the iterator's item to instead be a `usize` - /// indicating the length of the latest property value and writes the - override_writing_cstring: bool = false, - - pub const NameEncoding = enum { - utf8, - utf16, - /// Constructs the strings with a variable encoding using JSC's string - /// encoding API. - infer, - }; }; pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { - comptime if (options.override_writing_cstring) { - if (options.name_encoding != .utf8) { - @compileError(std.fmt.comptimePrint("{} is not a supported encoding when 'options.override_writing_cstring' is enabled. Try using utf8 instead.", .{options.name_encoding})); - } - }; - return struct { + /// Position in the property list array + /// Update is deferred until the next iteration i: u32 = 0, + + iter_i: u32 = 0, len: u32, array_ref: JSC.C.JSPropertyNameArrayRef, @@ -3704,29 +3730,16 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { /// Zero-sized when `options.include_value` is not enabled. global: if (options.include_value) JSC.C.JSContextRef else void, - /// The buffer for writing to when `options.override_writing_cstring` - /// is enabled. Zero-sized when `options.override_writing_cstring` is - /// not enabled. - cstring_buffer: if (options.override_writing_cstring) []u8 else void, - cstring_buffer_offset: if (options.override_writing_cstring) usize else void, - const Self = @This(); - pub const Item = switch (options.name_encoding) { - .utf8 => []const u8, - .utf16 => []const u16, - .infer => ZigString, - }; - inline fn initInternal(global: JSC.C.JSContextRef, object: JSC.C.JSObjectRef) Self { + const array_ref = JSC.C.JSObjectCopyPropertyNames(global, object); return .{ - .array_ref = JSC.C.JSObjectCopyPropertyNames(global, object), - .len = @intCast(u32, JSC.C.JSPropertyNameArrayGetCount(object)), + .array_ref = array_ref, + .len = @truncate(u32, JSC.C.JSPropertyNameArrayGetCount(array_ref)), .object = if (comptime options.include_value) object else .{}, .global = if (comptime options.include_value) global else .{}, .value = undefined, - .cstring_buffer = undefined, - .cstring_buffer_offset = undefined, }; } @@ -3739,75 +3752,23 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { return Self.initInternal(global, object); } - usingnamespace if (options.override_writing_cstring) struct { - /// Initializes the iterator using the CString buffer created using your - /// provided allocator. Note that this is requires two iterations for - /// each item at the slowest speed because we need to do a look-ahead - /// to preallocate the string buffer so it should only be used in - /// secular cases. - pub fn initCStringBuffer(global: JSC.C.JSContextRef, object: JSC.C.JSObjectRef, allocator: std.mem.Allocator) Self { - var self = Self.initInternal(global, object); - const total_len = self.peekTotalPropertyLengths(); - self.cstring_buffer = allocator.alloc(u8, total_len + self.len) catch unreachable; - self.cstring_buffer_offset = 0; - return self; - } - - /// Deinitializes the property name array and all of the string - /// references constructed by the copy along with the CString - /// buffer. The allocator the CString buffer was initialized with - /// **must** be the same as the one passed in here. - pub inline fn deinit(self: *Self, allocator: std.mem.Allocator) void { - JSC.C.JSPropertyNameArrayRelease(self.array_ref); - allocator.free(self.cstring_buffer); - } - - /// Deinitializes the property name array from JSC and returns the - /// CString buffer. The caller owns the returned buffer and free the - /// buffer with the same allocator as it was initialized with. - pub inline fn toOwnedCStringBuffer(self: Self) []u8 { - JSC.C.JSPropertyNameArrayRelease(self.array_ref); - return self.cstring_buffer; - } - } else struct { - /// Deinitializes the property name array and all of the string - /// references constructed by the copy. - pub inline fn deinit(self: *Self) void { - JSC.C.JSPropertyNameArrayRelease(self.array_ref); - } - }; + /// Deinitializes the property name array and all of the string + /// references constructed by the copy. + pub inline fn deinit(self: *Self) void { + JSC.C.JSPropertyNameArrayRelease(self.array_ref); + } /// Finds the next property string and, if `options.include_value` is /// enabled, updates the `iter.value` to respect the latest property's /// value. Also note the behavior of the other options. - pub fn next(self: *Self) ?Item { - if (self.i == self.len) return null; - - var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(self.array_ref, self.i); - self.i += 1; - - if (comptime options.override_writing_cstring) { - const start = self.cstring_buffer_offset; - - // The JSStringGetUTF8CString returns a null terminated string - // and writes to the buffer. We just need to adjust the length - // to update the slice to hold the items wrote to the pointer - // because we already those bytes are allocated from the initial - // iteration. - self.cstring_buffer_offset += JSC.C.JSStringGetUTF8CString(property_name_ref, self.cstring_buffer.ptr + start, self.cstring_buffer.len - start); - - const prop = self.cstring_buffer[start..self.cstring_buffer_offset]; - - if (comptime options.skip_empty_name) { - if (prop.len == 0) return self.next(); - } - - if (comptime options.include_value) { - self.value = JSC.JSValue.fromRef(JSC.C.JSObjectGetProperty(self.global, self.object, property_name_ref, null)); - } - - return prop; + pub fn next(self: *Self) ?ZigString { + if (self.iter_i >= self.len) { + self.i = self.iter_i; + return null; } + self.i = self.iter_i; + var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(self.array_ref, self.iter_i); + self.iter_i += 1; const len = JSC.C.JSStringGetLength(property_name_ref); @@ -3815,25 +3776,11 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { if (len == 0) return self.next(); } - const prop = switch (comptime options.name_encoding) { - .utf8 => JSC.C.JSStringGetCharacters8Ptr(property_name_ref)[0..len], - .utf16 => JSC.C.JSStringGetCharactersPtr(property_name_ref)[0..len], - .infer => blk: { - const enc = JSC.C.JSStringEncoding(property_name_ref); - break :blk switch (enc) { - .empty => ZigString.Empty, - .char8 => blk2: { - var s = ZigString.init((JSC.C.JSStringGetCharacters8Ptr(property_name_ref))[0..len]); - s.markUTF8(); - break :blk2 s; - }, - .char16 => blk2: { - var s = ZigString.init16(JSC.C.JSStringGetCharactersPtr(property_name_ref)[0..len]); - s.markUTF16(); - break :blk2 s; - }, - }; - }, + const prop = switch (JSC.C.JSStringEncoding(property_name_ref)) { + .empty => ZigString.Empty, + // latin1 + .char8 => ZigString.init((JSC.C.JSStringGetCharacters8Ptr(property_name_ref))[0..len]), + .char16 => ZigString.init16(JSC.C.JSStringGetCharactersPtr(property_name_ref)[0..len]), }; if (comptime options.include_value) { @@ -3842,20 +3789,5 @@ pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { return prop; } - - /// Finds the combined lengths of all of the unconsumed string property - /// names without advancing the iterator. Starts from the current index - /// in the iterator. - pub fn peekTotalPropertyLengths(self: *const Self) usize { - var i = self.i; - var total: usize = 0; - - while (i < self.len) : (i += 1) { - const ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(self.array_ref, i); - total += JSC.C.JSStringGetLength(ref); - } - - return total; - } }; } diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 14c6412f3..159bc4d0e 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -1930,7 +1930,7 @@ pub const ZigConsoleClient = struct { var props_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, - .name_encoding = .utf8, + .include_value = true, }).init(this.globalThis.ref(), props.asObjectRef()); defer props_iter.deinit(); @@ -1938,13 +1938,12 @@ pub const ZigConsoleClient = struct { var children_prop = props.get(this.globalThis, "children"); if (props_iter.len > 0) { { - var i: usize = 0; this.indent += 1; defer this.indent -|= 1; const count_without_children = props_iter.len - @as(usize, @boolToInt(children_prop != null)); while (props_iter.next()) |prop| { - if (strings.eqlComptime(prop, "children")) + if (prop.eqlComptime("children")) continue; var property_value = props_iter.value; @@ -1957,7 +1956,7 @@ pub const ZigConsoleClient = struct { writer.print( comptime Output.prettyFmt("<r><blue>{s}<d>=<r>", enable_ansi_colors), - .{prop[0..@minimum(prop.len, 128)]}, + .{prop.trunc(128)}, ); if (tag.cell.isStringLike()) { @@ -1977,17 +1976,17 @@ pub const ZigConsoleClient = struct { if ( // count_without_children is necessary to prevent printing an extra newline // if there are children and one prop and the child prop is the last prop - i + 1 < count_without_children and + props_iter.i + 1 < count_without_children and // 3 is arbitrary but basically // <input type="text" value="foo" /> // ^ should be one line // <input type="text" value="foo" bar="true" baz={false} /> // ^ should be multiple lines - i > 3) + props_iter.i > 3) { writer.writeAll("\n"); this.writeIndent(Writer, writer_) catch unreachable; - } else if (i + 1 < count_without_children) { + } else if (props_iter.i + 1 < count_without_children) { writer.writeAll(" "); } } @@ -2090,7 +2089,6 @@ pub const ZigConsoleClient = struct { { var props_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, - .name_encoding = .infer, .include_value = true, }).init(this.globalThis.ref(), object); defer props_iter.deinit(); diff --git a/src/js_ast.zig b/src/js_ast.zig index 3c6b6de44..eb28091c9 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -6993,7 +6993,6 @@ pub const Macro = struct { var array_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, - .name_encoding = .utf8, .include_value = true, }).init(writer.ctx, import_namespace_arg.asObjectRef()); defer array_iter.deinit(); @@ -7018,7 +7017,7 @@ pub const Macro = struct { if (!JSLexer.isIdentifier(alias)) throwTypeError(writer.ctx, "import alias must be an identifier", writer.exception); import.import.items[import_item_i] = ClauseItem{ - .alias = name, + .alias = name.toOwnedSlice(writer.allocator) catch return false, .original_name = alias, .name = .{ .loc = writer.loc, .ref = Ref.None }, .alias_loc = writer.loc, @@ -7934,7 +7933,6 @@ pub const Macro = struct { var object = value.asObjectRef(); var object_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, - .name_encoding = .utf8, .include_value = true, }).init(this.global.ref(), object); defer object_iter.deinit(); @@ -7952,7 +7950,7 @@ pub const Macro = struct { while (object_iter.next()) |prop| { properties[object_iter.i] = G.Property{ - .key = Expr.init(E.String, E.String.init(this.allocator.dupe(u8, prop) catch unreachable), this.caller.loc), + .key = Expr.init(E.String, E.String.init(prop.toOwnedSlice(this.allocator) catch unreachable), this.caller.loc), .value = try this.run(object_iter.value), }; } |