Skip to content

Commit ea6f8ce

Browse files
committed
Add more tests
Remove index and named setters, since they aren't working, and they aren't currently needed.
1 parent 180359e commit ea6f8ce

File tree

6 files changed

+235
-161
lines changed

6 files changed

+235
-161
lines changed

src/runtime/js.zig

Lines changed: 50 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
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

1519
const std = @import("std");
1620
const 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 {
22952203
test {
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
}

src/runtime/loop.zig

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
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

1519
const std = @import("std");
1620
const MemoryPool = std.heap.MemoryPool;

src/runtime/test_complex_types.zig

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
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

1519
const std = @import("std");
1620
const Allocator = std.mem.Allocator;

0 commit comments

Comments
 (0)