aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/javascript/jsc/bindings/bindings.zig10
-rw-r--r--src/js_ast.zig122
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();