diff options
-rw-r--r-- | src/javascript/jsc/bindings/bindings.zig | 10 | ||||
-rw-r--r-- | src/js_ast.zig | 122 |
2 files changed, 105 insertions, 27 deletions
diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 6377a52c9..3355fab44 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -1085,13 +1085,17 @@ pub const JSArrayIterator = struct { len: u32 = 0, array: JSValue, global: *JSGlobalObject, - + pub fn init(value: JSValue, global: *JSGlobalObject) JSArrayIterator { - return .{ .array = value, .global = global, .len = value.getLengthOfArray(global) }; + return .{ + .array = value, + .global = global, + .len = value.getLengthOfArray(global), + }; } pub fn next(this: *JSArrayIterator) ?JSValue { - if (this.i >= this.len) { + if (!(this.i < this.len)) { return null; } const i = this.i; diff --git a/src/js_ast.zig b/src/js_ast.zig index c33523bf9..291f59ff4 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -1200,6 +1200,7 @@ pub const E = struct { pub var empty = RegExp{ .value = "" }; pub fn pattern(this: RegExp) string { + // rewind until we reach the /foo/gim // ^ // should only ever be a single character @@ -1210,10 +1211,10 @@ pub const E = struct { i -= 1; } - return this.value[0..i]; + return std.mem.trim(u8, this.value[0..i], "/"); } - return this.value; + return std.mem.trim(u8, this.value, "/"); } pub fn flags(this: RegExp) string { @@ -4155,6 +4156,10 @@ pub const Macro = struct { .get = JSBindings.getCallArgs, .ro = true, }, + .properties = .{ + .get = JSBindings.getProperties, + .ro = true, + }, }, ); @@ -4197,6 +4202,32 @@ pub const Macro = struct { } } + pub fn getProperties( + this: *JSNode, + ctx: js.JSContextRef, + thisObject: js.JSValueRef, + prop: js.JSStringRef, + exception: js.ExceptionRef, + ) js.JSObjectRef { + const args = if (this.data == .e_object) this.data.e_object.properties else &[_]G.Property{}; + + switch (args.len) { + 0 => return js.JSObjectMakeArray(ctx, 0, null, exception), + 1...255 => { + var slice = temporary_call_args_array[0..args.len]; + for (slice) |_, i| { + var node = JSCBase.getAllocator(ctx).create(JSNode) catch unreachable; + node.* = JSNode{ .data = .{ .g_property = &args[i] }, .loc = this.loc }; + slice[i] = JSNode.Class.make(ctx, node); + } + return js.JSObjectMakeArray(ctx, args.len, slice.ptr, exception); + }, + else => { + return js.JSObjectMakeArray(ctx, 0, null, exception); + }, + } + } + fn toNumberValue(this: *JSNode, number: E.Number) js.JSValueRef { return JSC.JSValue.jsNumberFromDouble(number.value).asRef(); } @@ -5867,33 +5898,72 @@ pub const Macro = struct { switch (tag) { .e_array => { // var e_array: E.Array = E.Array{ .items = writer.allocator.alloc(E.Array, args.len) catch return false }; - const count = (writer.nextJSValue() orelse return false).toU16(); + var count = (writer.nextJSValue() orelse return false).toU16(); var i: u16 = 0; - var items = writer.allocator.alloc(ExprNodeIndex, count) catch return false; - - while (i < items.len) : (i += 1) { - switch (TagOrJSNode.fromJSValue(writer, writer.eatArg() orelse return false)) { - TagOrJSNode.tag => |tag_| { - if (!writer.writeFromJSWithTagInExpr(tag_, &items[i])) return false; - i += 1; - }, - TagOrJSNode.node => |node_| { - const node: JSNode = node_; - switch (node.data) { - JSNode.Tag.s_import => |import| { - return false; + var items = ExprList.initCapacity(writer.allocator, count) catch unreachable; + + while (i < count) { + var nextArg = writer.eatArg() orelse return false; + if (js.JSValueIsArray(writer.ctx, nextArg.asRef())) { + const extras = nextArg.getLengthOfArray(JavaScript.VirtualMachine.vm.global); + count += @truncate(u16, extras) - 1; + items.ensureUnusedCapacity(extras) catch unreachable; + items.expandToCapacity(); + var new_writer = writer.*; + new_writer.args_i = 0; + new_writer.args_len = extras; + new_writer.args_value = nextArg; + + while (new_writer.nextJSValue()) |value| { + defer i += 1; + switch (TagOrJSNode.fromJSValue(&new_writer, value)) { + TagOrJSNode.tag => |tag_| { + if (!new_writer.writeFromJSWithTagInExpr( + tag_, + &items.items[i], + )) return false; }, - else => { - items[i] = node.toExpr(); + TagOrJSNode.node => |node_| { + const node: JSNode = node_; + switch (node.data) { + JSNode.Tag.s_import => |import| { + return false; + }, + else => { + items.items[i] = node.toExpr(); + }, + } + }, + TagOrJSNode.invalid => { + return false; }, } - }, - TagOrJSNode.invalid => { - return false; - }, + } + } else { + defer i += 1; + + switch (TagOrJSNode.fromJSValue(writer, nextArg)) { + TagOrJSNode.tag => |tag_| { + if (!writer.writeFromJSWithTagInExpr(tag_, &items.items[i])) return false; + }, + TagOrJSNode.node => |node_| { + const node: JSNode = node_; + switch (node.data) { + JSNode.Tag.s_import => |import| { + return false; + }, + else => { + items.items[i] = node.toExpr(); + }, + } + }, + TagOrJSNode.invalid => { + return false; + }, + } } } - expr.* = Expr.alloc(writer.allocator, E.Array, E.Array{ .items = items }, writer.loc); + expr.* = Expr.alloc(writer.allocator, E.Array, E.Array{ .items = items.items[0..i] }, writer.loc); return true; }, .e_boolean => { @@ -6134,7 +6204,9 @@ pub const Macro = struct { if (writer.writeFromJS()) |node| { var ptr = writer.allocator.create(JSNode) catch unreachable; ptr.* = node; - return JSNode.Class.make(ctx, ptr); + var result = JSNode.Class.make(ctx, ptr); + js.JSValueProtect(ctx, result); + return result; } return null; @@ -6220,6 +6292,8 @@ pub const Macro = struct { var macro_callback = macro.vm.macros.get(id) orelse return caller; var result = js.JSObjectCallAsFunctionReturnValue(macro.vm.global.ref(), macro_callback, null, args.len + 1, &args_buf); + js.JSValueProtect(macro.vm.global.ref(), result.asRef()); + defer js.JSValueUnprotect(macro.vm.global.ref(), result.asRef()); var promise = JSC.JSPromise.resolvedPromise(macro.vm.global, result); macro.vm.global.vm().drainMicrotasks(); |