diff options
author | 2021-09-27 21:01:34 -0700 | |
---|---|---|
committer | 2021-09-27 21:01:34 -0700 | |
commit | 13f62973128aea9266b43cc2e0de1e7bf1768b52 (patch) | |
tree | 4c3544ead51e6fabcec3716468d52ecf25099d8b | |
parent | f9dfa226a56eb02f33e81aa675e1011fbcf405fe (diff) | |
download | bun-13f62973128aea9266b43cc2e0de1e7bf1768b52.tar.gz bun-13f62973128aea9266b43cc2e0de1e7bf1768b52.tar.zst bun-13f62973128aea9266b43cc2e0de1e7bf1768b52.zip |
Access object properties from macros
-rw-r--r-- | src/javascript/jsc/base.zig | 13 | ||||
-rw-r--r-- | src/js_ast.zig | 119 |
2 files changed, 128 insertions, 4 deletions
diff --git a/src/javascript/jsc/base.zig b/src/javascript/jsc/base.zig index a5f2d336d..b0583dc53 100644 --- a/src/javascript/jsc/base.zig +++ b/src/javascript/jsc/base.zig @@ -1360,6 +1360,16 @@ pub fn NewClass( ).rfn; def.callAsFunction = callback; + } else if (comptime strings.eqlComptime(function_names[i], "hasProperty")) { + def.hasProperty = @field(staticFunctions, "hasProperty").rfn; + } else if (comptime strings.eqlComptime(function_names[i], "getProperty")) { + def.getProperty = @field(staticFunctions, "getProperty").rfn; + } else if (comptime strings.eqlComptime(function_names[i], "setProperty")) { + def.setProperty = @field(staticFunctions, "setProperty").rfn; + } else if (comptime strings.eqlComptime(function_names[i], "deleteProperty")) { + def.deleteProperty = @field(staticFunctions, "deleteProperty").rfn; + } else if (comptime strings.eqlComptime(function_names[i], "getPropertyNames")) { + def.getPropertyNames = @field(staticFunctions, "getPropertyNames").rfn; } else { const CtxField = @field(staticFunctions, function_names[i]); if (comptime !@hasField(@TypeOf(CtxField), "rfn")) { @@ -1540,7 +1550,7 @@ pub fn castObj(obj: js.JSObjectRef, comptime Type: type) *Type { return JSPrivateDataPtr.from(js.JSObjectGetPrivate(obj)).as(Type); } const JSNode = @import("../../js_ast.zig").Macro.JSNode; - +const LazyPropertiesObject = @import("../../js_ast.zig").Macro.LazyPropertiesObject; pub const JSPrivateDataPtr = TaggedPointerUnion(.{ ResolveError, BuildError, @@ -1551,6 +1561,7 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{ Body, Router, JSNode, + LazyPropertiesObject, }); pub inline fn GetJSPrivateData(comptime Type: type, ref: js.JSObjectRef) ?*Type { diff --git a/src/js_ast.zig b/src/js_ast.zig index 4e1f091d0..aabc756b6 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -4160,6 +4160,10 @@ pub const Macro = struct { .get = JSBindings.getProperties, .ro = true, }, + .propertyNodes = .{ + .get = JSBindings.getPropertyNodes, + .ro = true, + }, }, ); @@ -4209,6 +4213,22 @@ pub const Macro = struct { prop: js.JSStringRef, exception: js.ExceptionRef, ) js.JSObjectRef { + if (this.data != .e_object) { + return js.JSObjectMake(ctx, null, null); + } + + var lazy = getAllocator(ctx).create(LazyPropertiesObject) catch unreachable; + lazy.* = LazyPropertiesObject{ .node = this.* }; + return LazyPropertiesObject.Class.make(ctx, lazy); + } + + pub fn getPropertyNodes( + 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) { @@ -4317,7 +4337,9 @@ pub const Macro = struct { } fn toObjectPrimitive(this: *JSNode, ctx: js.JSContextRef, obj: E.Object, exception: js.ExceptionRef) js.JSObjectRef { - return toObjectValue(this, ctx, obj, exception); + var lazy = getAllocator(ctx).create(LazyPropertiesObject) catch unreachable; + lazy.* = LazyPropertiesObject{ .node = this.* }; + return LazyPropertiesObject.Class.make(ctx, lazy); } fn toPropertyPrimitive(this: *JSNode, ctx: js.JSContextRef, prop: G.Property, exception: js.ExceptionRef) js.JSObjectRef { @@ -4426,11 +4448,9 @@ pub const Macro = struct { return JSBindings.toRegexValue(this, ctx, regex, exception); }, .e_object => |object| { - if (comptime !allow_recursion) return js.JSValueMakeUndefined(ctx); return JSBindings.toObjectPrimitive(this, ctx, object.*, exception); }, .e_array => |array| { - if (comptime !allow_recursion) return js.JSValueMakeUndefined(ctx); return JSBindings.toArrayPrimitive(this, ctx, array.*, exception); }, @@ -6213,6 +6233,99 @@ pub const Macro = struct { } }; + pub const LazyPropertiesObject = struct { + node: JSNode, + + pub const Class = JSCBase.NewClass( + LazyPropertiesObject, + .{ + .name = "LazyPropertiesObject", + .read_only = true, + }, + .{ + .getProperty = .{ + .rfn = getProperty, + }, + .hasProperty = .{ + .rfn = hasProperty, + }, + .getPropertyNames = .{ + .rfn = getPropertyNames, + }, + }, + .{}, + ); + + pub fn getProperty( + ctx: js.JSContextRef, + thisObject: js.JSObjectRef, + propertyName: js.JSStringRef, + exception: js.ExceptionRef, + ) callconv(.C) js.JSValueRef { + var this: *LazyPropertiesObject = JSCBase.GetJSPrivateData(LazyPropertiesObject, thisObject) orelse return null; + + const len = js.JSStringGetLength(propertyName); + const properties = this.node.data.e_object.properties; + var ptr = js.JSStringGetCharacters8Ptr(propertyName); + var property_slice = ptr[0..len]; + var value_node: JSNode = undefined; + + for (properties) |property| { + const key = property.key orelse continue; + if (key.data != .e_string) continue; + const str = key.data.e_string.utf8; + + if (strings.eql(property_slice, str)) { + const value = property.value orelse return js.JSValueMakeUndefined(ctx); + value_node = JSNode.initExpr(value); + return JSNode.JSBindings.toPrimitive(&value_node, ctx, exception); + } + } + + return js.JSValueMakeUndefined(ctx); + } + + pub fn hasProperty( + ctx: js.JSContextRef, + thisObject: js.JSObjectRef, + propertyName: js.JSStringRef, + ) callconv(.C) bool { + var this: *LazyPropertiesObject = JSCBase.GetJSPrivateData(LazyPropertiesObject, thisObject) orelse return false; + + const len = js.JSStringGetLength(propertyName); + const properties = this.node.data.e_object.properties; + var ptr = js.JSStringGetCharacters8Ptr(propertyName); + var property_slice = ptr[0..len]; + + for (properties) |property| { + const key = property.key orelse continue; + if (key.data != .e_string) continue; + const str = key.data.e_string.utf8; + + if (strings.eql(property_slice, str)) return true; + } + + return false; + } + + pub fn getPropertyNames( + ctx: js.JSContextRef, + thisObject: js.JSObjectRef, + props: js.JSPropertyNameAccumulatorRef, + ) callconv(.C) void { + var this: *LazyPropertiesObject = JSCBase.GetJSPrivateData(LazyPropertiesObject, thisObject) orelse return; + + const properties = this.node.data.e_object.properties; + + for (properties) |property| { + const key = property.key orelse continue; + if (key.data != .e_string) continue; + const str = key.data.e_string.utf8; + js.JSPropertyNameAccumulatorAddName(props, js.JSStringCreateStatic(str.ptr, str.len)); + } + } + }; + resolver: *Resolver, vm: *JavaScript.VirtualMachine = undefined, |