1- // Copyright 2023-2024 Lightpanda (Selecy SAS)
1+ // Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
22//
3- // Licensed under the Apache License, Version 2.0 (the "License");
4- // you may not use this file except in compliance with the License.
5- // You may obtain a copy of the License at
3+ // Francis Bouvier <[email protected] > 4+ // Pierre Tachoire <[email protected] > 65//
7- // http://www.apache.org/licenses/LICENSE-2.0
6+ // This program is free software: you can redistribute it and/or modify
7+ // it under the terms of the GNU Affero General Public License as
8+ // published by the Free Software Foundation, either version 3 of the
9+ // License, or (at your option) any later version.
810//
9- // Unless required by applicable law or agreed to in writing, software
10- // distributed under the License is distributed on an "AS IS" BASIS,
11- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12- // See the License for the specific language governing permissions and
13- // limitations under the License.
11+ // This program is distributed in the hope that it will be useful,
12+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ // GNU Affero General Public License for more details.
15+ //
16+ // You should have received a copy of the GNU Affero General Public License
17+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
1418
1519const std = @import ("std" );
1620const builtin = @import ("builtin" );
@@ -548,12 +552,11 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
548552 }
549553
550554 fn generateIndexer (_ : * Self , comptime Struct : type , template_proto : v8.ObjectTemplate ) void {
551- var has_one = false ;
552- var configuration = v8.IndexedPropertyHandlerConfiguration {};
553-
554- if (@hasDecl (Struct , "indexed_get" )) {
555- has_one = true ;
556- configuration .getter = struct {
555+ if (@hasDecl (Struct , "indexed_get" ) == false ) {
556+ return ;
557+ }
558+ const configuration = v8.IndexedPropertyHandlerConfiguration {
559+ .getter = struct {
557560 fn callback (idx : u32 , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) void {
558561 const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
559562 var caller = Caller (Self ).init (info );
@@ -564,44 +567,25 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
564567 caller .handleError (named_function , err , info );
565568 };
566569 }
567- }.callback ;
568- }
569-
570- if (@hasDecl (Struct , "indexed_set" )) {
571- has_one = true ;
572- configuration .setter = struct {
573- fn callback (idx : u32 , raw_value : ? * const v8.C_Value , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) void {
574- const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
575- var caller = Caller (Self ).init (info );
576- defer caller .deinit ();
577-
578- const js_value = v8.Value { .handle = raw_value .? };
579- const named_function = NamedFunction (Struct , Struct .indexed_set , "indexed_set" ){};
580- caller .setIndex (named_function , idx , js_value , info ) catch | err | {
581- caller .handleError (named_function , err , info );
582- };
583- }
584- }.callback ;
585- }
570+ }.callback ,
571+ };
586572
587- if (has_one ) {
588- template_proto .setIndexedProperty (configuration , null );
589- }
573+ // If you're trying to implement setter, read:
574+ // https://groups.google.com/g/v8-users/c/8tahYBsHpgY/m/IteS7Wn2AAAJ
575+ // The issue I had was
576+ // (a) where to attache it: does it go ont he instance_template
577+ // instead of the prototype?
578+ // (b) defining the getter or query to respond with the
579+ // PropertyAttribute to indicate if the property can be set
580+ template_proto .setIndexedProperty (configuration , null );
590581 }
591582
592583 fn generateNamedIndexer (_ : * Self , comptime Struct : type , template_proto : v8.ObjectTemplate ) void {
593- var has_one = false ;
594- var configuration = v8.NamedPropertyHandlerConfiguration {
595- // This is really cool. Without this, we'd intercept _all_ properties
596- // even those explicitly set. So, node.length for example would get routed
597- // to our `named_get`, rather than a `get_length`. This might be
598- // useful if we run into a type that we can't model properly in Zig.
599- .flags = v8 .PropertyHandlerFlags .OnlyInterceptStrings | v8 .PropertyHandlerFlags .NonMasking ,
600- };
601-
602- if (@hasDecl (Struct , "named_get" )) {
603- has_one = true ;
604- configuration .getter = struct {
584+ if (@hasDecl (Struct , "named_get" ) == false ) {
585+ return ;
586+ }
587+ const configuration = v8.NamedPropertyHandlerConfiguration {
588+ .getter = struct {
605589 fn callback (c_name : ? * const v8.C_Name , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) void {
606590 const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
607591 var caller = Caller (Self ).init (info );
@@ -612,29 +596,23 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
612596 caller .handleError (named_function , err , info );
613597 };
614598 }
615- }.callback ;
616- }
599+ }.callback ,
617600
618- if (@hasDecl (Struct , "named_set" )) {
619- has_one = true ;
620- configuration .setter = struct {
621- fn callback (c_name : ? * const v8.C_Name , raw_value : ? * const v8.C_Value , raw_info : ? * const v8.C_PropertyCallbackInfo ) callconv (.c ) void {
622- const info = v8 .PropertyCallbackInfo .initFromV8 (raw_info );
623- var caller = Caller (Self ).init (info );
624- defer caller .deinit ();
625-
626- const js_value = v8.Value { .handle = raw_value .? };
627- const named_function = NamedFunction (Struct , Struct .named_set , "named_set" ){};
628- caller .setNamedIndex (named_function , .{ .handle = c_name .? }, js_value , info ) catch | err | {
629- caller .handleError (named_function , err , info );
630- };
631- }
632- }.callback ;
633- }
601+ // This is really cool. Without this, we'd intercept _all_ properties
602+ // even those explicitly set. So, node.length for example would get routed
603+ // to our `named_get`, rather than a `get_length`. This might be
604+ // useful if we run into a type that we can't model properly in Zig.
605+ .flags = v8 .PropertyHandlerFlags .OnlyInterceptStrings | v8 .PropertyHandlerFlags .NonMasking ,
606+ };
634607
635- if (has_one ) {
636- template_proto .setNamedProperty (configuration , null );
637- }
608+ // If you're trying to implement setter, read:
609+ // https://groups.google.com/g/v8-users/c/8tahYBsHpgY/m/IteS7Wn2AAAJ
610+ // The issue I had was
611+ // (a) where to attache it: does it go ont he instance_template
612+ // instead of the prototype?
613+ // (b) defining the getter or query to respond with the
614+ // PropertyAttribute to indicate if the property can be set
615+ template_proto .setNamedProperty (configuration , null );
638616 }
639617
640618 // Turns a Zig value into a JS one.
@@ -1508,41 +1486,6 @@ fn Caller(comptime E: type) type {
15081486 }
15091487 }
15101488
1511- fn setIndex (self : * Self , comptime named_function : anytype , idx : u32 , js_value : v8.Value , info : v8.PropertyCallbackInfo ) ! void {
1512- const S = named_function .S ;
1513- comptime assertSelfReceiver (named_function );
1514-
1515- const zig_instance = try E .typeTaggedAnyOpaque (named_function , * Receiver (S ), info .getThis ());
1516-
1517- const IndexedSet = @TypeOf (named_function .func );
1518- var args : ParamterTypes (IndexedSet ) = undefined ;
1519- const arg_fields = @typeInfo (@TypeOf (args )).@"struct" .fields ;
1520- switch (arg_fields .len ) {
1521- 0 , 1 , 2 = > @compileError (named_function .full_name ++ " must take at least a u32 parameter and a value" ),
1522- 3 , 4 = > {
1523- @field (args , "0" ) = zig_instance ;
1524- @field (args , "1" ) = idx ;
1525- @field (args , "2" ) = try self .jsValueToZig (named_function , arg_fields [2 ].type , js_value );
1526- if (comptime arg_fields .len == 4 ) {
1527- comptime assertIsStateArg (named_function , 3 );
1528- @field (args , "3" ) = self .executor .state ;
1529- }
1530- },
1531- else = > @compileError (named_function .full_name ++ " has too many parmaters" ),
1532- }
1533-
1534- switch (@typeInfo (@typeInfo (IndexedSet ).@"fn" .return_type .? )) {
1535- .error_union = > | eu | {
1536- if (eu .payload == void ) {
1537- return @call (.auto , S .indexed_set , args );
1538- }
1539- },
1540- .void = > return @call (.auto , S .indexed_set , args ),
1541- else = > {},
1542- }
1543- @compileError (named_function .full_name ++ " cannot have a return type" );
1544- }
1545-
15461489 fn getNamedIndex (self : * Self , comptime named_function : anytype , name : v8.Name , info : v8.PropertyCallbackInfo ) ! void {
15471490 const S = named_function .S ;
15481491 const NamedGet = @TypeOf (named_function .func );
@@ -1579,41 +1522,6 @@ fn Caller(comptime E: type) type {
15791522 }
15801523 }
15811524
1582- fn setNamedIndex (self : * Self , comptime named_function : anytype , name : v8.Name , js_value : v8.Value , info : v8.PropertyCallbackInfo ) ! void {
1583- const S = named_function .S ;
1584- comptime assertSelfReceiver (named_function );
1585-
1586- const zig_instance = try E .typeTaggedAnyOpaque (named_function , * Receiver (S ), info .getThis ());
1587-
1588- const IndexedSet = @TypeOf (named_function .func );
1589- var args : ParamterTypes (IndexedSet ) = undefined ;
1590- const arg_fields = @typeInfo (@TypeOf (args )).@"struct" .fields ;
1591- switch (arg_fields .len ) {
1592- 0 , 1 , 2 = > @compileError (named_function .full_name ++ " must take at least an u32 parameter and a value" ),
1593- 3 , 4 = > {
1594- @field (args , "0" ) = zig_instance ;
1595- @field (args , "1" ) = try self .nameToString (name );
1596- @field (args , "2" ) = try self .jsValueToZig (named_function , arg_fields [2 ].type , js_value );
1597- if (comptime arg_fields .len == 4 ) {
1598- comptime assertIsStateArg (named_function , 3 );
1599- @field (args , "3" ) = self .executor .state ;
1600- }
1601- },
1602- else = > @compileError (named_function .full_name ++ " has too many parmaters" ),
1603- }
1604-
1605- switch (@typeInfo (@typeInfo (IndexedSet ).@"fn" .return_type .? )) {
1606- .error_union = > | eu | {
1607- if (eu .payload == void ) {
1608- return @call (.auto , S .named_set , args );
1609- }
1610- },
1611- .void = > return @call (.auto , S .named_set , args ),
1612- else = > {},
1613- }
1614- @compileError (named_function .full_name ++ " cannot have a return type" );
1615- }
1616-
16171525 fn nameToString (self : * Self , name : v8.Name ) ! []const u8 {
16181526 return valueToString (self .call_allocator , .{ .handle = name .handle }, self .isolate , self .context );
16191527 }
@@ -2295,4 +2203,5 @@ fn getTaggedAnyOpaque(value: v8.Value) ?*TaggedAnyOpaque {
22952203test {
22962204 std .testing .refAllDecls (@import ("test_primitive_types.zig" ));
22972205 std .testing .refAllDecls (@import ("test_complex_types.zig" ));
2206+ std .testing .refAllDecls (@import ("test_object_types.zig" ));
22982207}
0 commit comments