mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +00:00
migrate almost all types
This commit is contained in:
@@ -43,7 +43,24 @@ pub fn get(self: Array, index: u32) !js.Value {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asObject(self: Array) js.Object {
|
pub fn set(self: Array, index: u32, value: anytype, comptime opts: js.bridge.Caller.CallOpts) !bool {
|
||||||
|
const ctx = self.ctx;
|
||||||
|
|
||||||
|
const js_value = try ctx.zigValueToJs(value, opts);
|
||||||
|
|
||||||
|
var out: v8.c.MaybeBool = undefined;
|
||||||
|
v8.c.v8__Object__SetAtIndex(@ptrCast(self.handle), ctx.handle, index, js_value.handle, &out);
|
||||||
|
return out.has_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toObject(self: Array) js.Object {
|
||||||
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
|
.handle = @ptrCast(self.handle),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toValue(self: Array) js.Value {
|
||||||
return .{
|
return .{
|
||||||
.ctx = self.ctx,
|
.ctx = self.ctx,
|
||||||
.handle = @ptrCast(self.handle),
|
.handle = @ptrCast(self.handle),
|
||||||
|
|||||||
@@ -23,26 +23,23 @@ const BigInt = @This();
|
|||||||
|
|
||||||
handle: *const v8.c.Integer,
|
handle: *const v8.c.Integer,
|
||||||
|
|
||||||
pub fn initI64(isolate_handle: *v8.c.Isolate, val: i64) BigInt {
|
pub fn init(isolate: *v8.c.Isolate, val: anytype) BigInt {
|
||||||
return .{
|
const handle = switch (@TypeOf(val)) {
|
||||||
.handle = v8.c.v8__BigInt__New(isolate_handle, val).?,
|
i8, i16, i32, i64, isize => v8.c.v8__BigInt__New(isolate, val).?,
|
||||||
|
u8, u16, u32, u64, usize => v8.c.v8__BigInt__NewFromUnsigned(isolate, val).?,
|
||||||
|
else => |T| @compileError("cannot create v8::BigInt from: " ++ @typeName(T)),
|
||||||
};
|
};
|
||||||
}
|
return .{ .handle = handle };
|
||||||
|
|
||||||
pub fn initU64(isolate_handle: *v8.c.Isolate, val: u64) BigInt {
|
|
||||||
return .{
|
|
||||||
.handle = v8.c.v8__BigInt__NewFromUnsigned(isolate_handle, val).?,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getUint64(self: BigInt) u64 {
|
|
||||||
return v8.c.v8__BigInt__Uint64Value(self.handle, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getInt64(self: BigInt) i64 {
|
pub fn getInt64(self: BigInt) i64 {
|
||||||
return v8.c.v8__BigInt__Int64Value(self.handle, null);
|
return v8.c.v8__BigInt__Int64Value(self.handle, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getUint64(self: BigInt) u64 {
|
||||||
|
return v8.c.v8__BigInt__Uint64Value(self.handle, null);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toValue(self: BigInt) js.Value {
|
pub fn toValue(self: BigInt) js.Value {
|
||||||
return .{
|
return .{
|
||||||
.ctx = undefined, // Will be set by caller if needed
|
.ctx = undefined, // Will be set by caller if needed
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -137,7 +137,7 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context
|
|||||||
var context = &self.context.?;
|
var context = &self.context.?;
|
||||||
// Store a pointer to our context inside the v8 context so that, given
|
// Store a pointer to our context inside the v8 context so that, given
|
||||||
// a v8 context, we can get our context out
|
// a v8 context, we can get our context out
|
||||||
const data = isolate.initBigIntU64(@intCast(@intFromPtr(context)));
|
const data = isolate.initBigInt(@intFromPtr(context));
|
||||||
v8.c.v8__Context__SetEmbedderData(context_handle, 1, @ptrCast(data.handle));
|
v8.c.v8__Context__SetEmbedderData(context_handle, 1, @ptrCast(data.handle));
|
||||||
|
|
||||||
try context.setupGlobal();
|
try context.setupGlobal();
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ pub fn tryCallWithThis(self: *const Function, comptime T: type, this: anytype, a
|
|||||||
pub fn callWithThis(self: *const Function, comptime T: type, this: anytype, args: anytype) !T {
|
pub fn callWithThis(self: *const Function, comptime T: type, this: anytype, args: anytype) !T {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
// When we're calling a function from within JavaScript itself, this isn't
|
// When we're calling a function from within JavaScript itself, this isn't
|
||||||
// necessary. We're within a Caller instantiation, which will already have
|
// necessary. We're within a Caller instantiation, which will already have
|
||||||
// incremented the call_depth and it won't decrement it until the Caller is
|
// incremented the call_depth and it won't decrement it until the Caller is
|
||||||
@@ -122,10 +121,6 @@ pub fn callWithThis(self: *const Function, comptime T: type, this: anytype, args
|
|||||||
defer context.call_depth = call_depth;
|
defer context.call_depth = call_depth;
|
||||||
|
|
||||||
const js_this = blk: {
|
const js_this = blk: {
|
||||||
if (@TypeOf(this) == v8.Object) {
|
|
||||||
break :blk this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@TypeOf(this) == js.Object) {
|
if (@TypeOf(this) == js.Object) {
|
||||||
break :blk this.js_obj;
|
break :blk this.js_obj;
|
||||||
}
|
}
|
||||||
@@ -180,9 +175,8 @@ pub fn src(self: *const Function) ![]const u8 {
|
|||||||
|
|
||||||
pub fn getPropertyValue(self: *const Function, name: []const u8) !?js.Value {
|
pub fn getPropertyValue(self: *const Function, name: []const u8) !?js.Value {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle };
|
const key = ctx.isolate.initStringHandle(name);
|
||||||
const key = v8.String.initUtf8(v8_isolate, name);
|
const handle = v8.c.v8__Object__Get(self.handle, ctx.handle, key) orelse {
|
||||||
const handle = v8.c.v8__Object__Get(self.handle, ctx.handle, key.handle) orelse {
|
|
||||||
return error.JsException;
|
return error.JsException;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ pub fn performMicrotasksCheckpoint(self: Isolate) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueueMicrotask(self: Isolate, callback: anytype, data: anytype) void {
|
pub fn enqueueMicrotask(self: Isolate, callback: anytype, data: anytype) void {
|
||||||
const v8_isolate = v8.Isolate{ .handle = self.handle };
|
v8.c.v8__Isolate__EnqueueMicrotask(self.handle, callback, data);
|
||||||
v8_isolate.enqueueMicrotask(callback, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueueMicrotaskFunc(self: Isolate, function: js.Function) void {
|
pub fn enqueueMicrotaskFunc(self: Isolate, function: js.Function) void {
|
||||||
@@ -68,40 +67,46 @@ pub fn throwException(self: Isolate, value: *const v8.c.Value) *const v8.c.Value
|
|||||||
return v8.c.v8__Isolate__ThrowException(self.handle, value).?;
|
return v8.c.v8__Isolate__ThrowException(self.handle, value).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createStringHandle(self: Isolate, str: []const u8) *const v8.c.String {
|
pub fn initStringHandle(self: Isolate, str: []const u8) *const v8.c.String {
|
||||||
return v8.c.v8__String__NewFromUtf8(self.handle, str.ptr, v8.c.kNormal, @as(c_int, @intCast(str.len))).?;
|
return v8.c.v8__String__NewFromUtf8(self.handle, str.ptr, v8.c.kNormal, @as(c_int, @intCast(str.len))).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createError(self: Isolate, msg: []const u8) *const v8.c.Value {
|
pub fn createError(self: Isolate, msg: []const u8) *const v8.c.Value {
|
||||||
const message = self.createStringHandle(msg);
|
const message = self.initStringHandle(msg);
|
||||||
return v8.c.v8__Exception__Error(message).?;
|
return v8.c.v8__Exception__Error(message).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createTypeError(self: Isolate, msg: []const u8) *const v8.c.Value {
|
pub fn createTypeError(self: Isolate, msg: []const u8) *const v8.c.Value {
|
||||||
const message = self.createStringHandle(msg);
|
const message = self.initStringHandle(msg);
|
||||||
return v8.c.v8__Exception__TypeError(message).?;
|
return v8.c.v8__Exception__TypeError(message).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initArray(self: Isolate, len: u32) v8.Array {
|
|
||||||
const handle = v8.c.v8__Array__New(self.handle, @intCast(len)).?;
|
|
||||||
return .{ .handle = handle };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initObject(self: Isolate) v8.Object {
|
|
||||||
const handle = v8.c.v8__Object__New(self.handle).?;
|
|
||||||
return .{ .handle = handle };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initString(self: Isolate, str: []const u8) v8.String {
|
|
||||||
return .{ .handle = self.createStringHandle(str) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initNull(self: Isolate) *const v8.c.Value {
|
pub fn initNull(self: Isolate) *const v8.c.Value {
|
||||||
return v8.c.v8__Null(self.handle).?;
|
return v8.c.v8__Null(self.handle).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initBigIntU64(self: Isolate, val: u64) js.BigInt {
|
pub fn initUndefined(self: Isolate) *const v8.c.Value {
|
||||||
return js.BigInt.initU64(self.handle, val);
|
return v8.c.v8__Undefined(self.handle).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initFalse(self: Isolate) *const v8.c.Value {
|
||||||
|
return v8.c.v8__False(self.handle).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initTrue(self: Isolate) *const v8.c.Value {
|
||||||
|
return v8.c.v8__True(self.handle).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initInteger(self: Isolate, val: anytype) js.Integer {
|
||||||
|
return js.Integer.init(self.handle, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initBigInt(self: Isolate, val: anytype) js.BigInt {
|
||||||
|
return js.BigInt.init(self.handle, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initNumber(self: Isolate, val: anytype) js.Number {
|
||||||
|
return js.Number.init(self.handle, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createContextHandle(self: Isolate, global_tmpl: ?*const v8.c.ObjectTemplate, global_obj: ?*const v8.c.Value) *const v8.c.Context {
|
pub fn createContextHandle(self: Isolate, global_tmpl: ?*const v8.c.ObjectTemplate, global_obj: ?*const v8.c.Value) *const v8.c.Context {
|
||||||
@@ -111,3 +116,7 @@ pub fn createContextHandle(self: Isolate, global_tmpl: ?*const v8.c.ObjectTempla
|
|||||||
pub fn createFunctionTemplateHandle(self: Isolate) *const v8.c.FunctionTemplate {
|
pub fn createFunctionTemplateHandle(self: Isolate) *const v8.c.FunctionTemplate {
|
||||||
return v8.c.v8__FunctionTemplate__New__DEFAULT(self.handle).?;
|
return v8.c.v8__FunctionTemplate__New__DEFAULT(self.handle).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn createExternal(self: Isolate, val: *anyopaque) *const v8.c.External {
|
||||||
|
return v8.c.v8__External__New(self.handle, val).?;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ const v8 = js.v8;
|
|||||||
|
|
||||||
const Module = @This();
|
const Module = @This();
|
||||||
|
|
||||||
|
ctx: *js.Context,
|
||||||
|
handle: *const v8.c.Module,
|
||||||
|
|
||||||
pub const Status = enum(u32) {
|
pub const Status = enum(u32) {
|
||||||
kUninstantiated = v8.c.kUninstantiated,
|
kUninstantiated = v8.c.kUninstantiated,
|
||||||
kInstantiating = v8.c.kInstantiating,
|
kInstantiating = v8.c.kInstantiating,
|
||||||
@@ -30,49 +33,54 @@ pub const Status = enum(u32) {
|
|||||||
kErrored = v8.c.kErrored,
|
kErrored = v8.c.kErrored,
|
||||||
};
|
};
|
||||||
|
|
||||||
handle: *const v8.c.Module,
|
|
||||||
|
|
||||||
pub fn getStatus(self: Module) Status {
|
pub fn getStatus(self: Module) Status {
|
||||||
return @enumFromInt(v8.c.v8__Module__GetStatus(self.handle));
|
return @enumFromInt(v8.c.v8__Module__GetStatus(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getException(self: Module) v8.Value {
|
pub fn getException(self: Module) js.Value {
|
||||||
return .{
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
.handle = v8.c.v8__Module__GetException(self.handle).?,
|
.handle = v8.c.v8__Module__GetException(self.handle).?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getModuleRequests(self: Module) v8.FixedArray {
|
pub fn getModuleRequests(self: Module) Requests {
|
||||||
return .{
|
return .{
|
||||||
|
.ctx = self.ctx.handle,
|
||||||
.handle = v8.c.v8__Module__GetModuleRequests(self.handle).?,
|
.handle = v8.c.v8__Module__GetModuleRequests(self.handle).?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate(self: Module, ctx_handle: *const v8.c.Context, cb: v8.c.ResolveModuleCallback) !bool {
|
pub fn instantiate(self: Module, cb: v8.c.ResolveModuleCallback) !bool {
|
||||||
var out: v8.c.MaybeBool = undefined;
|
var out: v8.c.MaybeBool = undefined;
|
||||||
v8.c.v8__Module__InstantiateModule(self.handle, ctx_handle, cb, &out);
|
v8.c.v8__Module__InstantiateModule(self.handle, self.ctx.handle, cb, &out);
|
||||||
if (out.has_value) {
|
if (out.has_value) {
|
||||||
return out.value;
|
return out.value;
|
||||||
}
|
}
|
||||||
return error.JsException;
|
return error.JsException;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn evaluate(self: Module, ctx_handle: *const v8.c.Context) !v8.Value {
|
pub fn evaluate(self: Module) !js.Value {
|
||||||
const res = v8.c.v8__Module__Evaluate(self.handle, ctx_handle) orelse return error.JsException;
|
const ctx = self.ctx;
|
||||||
|
const res = v8.c.v8__Module__Evaluate(self.handle, ctx.handle) orelse return error.JsException;
|
||||||
|
|
||||||
if (self.getStatus() == .kErrored) {
|
if (self.getStatus() == .kErrored) {
|
||||||
return error.JsException;
|
return error.JsException;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .{ .handle = res };
|
return .{
|
||||||
|
.ctx = ctx,
|
||||||
|
.handle = res,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getIdentityHash(self: Module) u32 {
|
pub fn getIdentityHash(self: Module) u32 {
|
||||||
return @bitCast(v8.c.v8__Module__GetIdentityHash(self.handle));
|
return @bitCast(v8.c.v8__Module__GetIdentityHash(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getModuleNamespace(self: Module) v8.Value {
|
pub fn getModuleNamespace(self: Module) js.Value {
|
||||||
return .{
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
.handle = v8.c.v8__Module__GetModuleNamespace(self.handle).?,
|
.handle = v8.c.v8__Module__GetModuleNamespace(self.handle).?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -80,3 +88,36 @@ pub fn getModuleNamespace(self: Module) v8.Value {
|
|||||||
pub fn getScriptId(self: Module) u32 {
|
pub fn getScriptId(self: Module) u32 {
|
||||||
return @intCast(v8.c.v8__Module__ScriptId(self.handle));
|
return @intCast(v8.c.v8__Module__ScriptId(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn persist(self: Module) !Module {
|
||||||
|
var ctx = self.ctx;
|
||||||
|
|
||||||
|
const global = js.Global(Module).init(ctx.isolate.handle, self.handle);
|
||||||
|
try ctx.global_modules.append(ctx.arena, global);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.ctx = ctx,
|
||||||
|
.handle = global.local(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const Requests = struct {
|
||||||
|
ctx: *const v8.c.Context,
|
||||||
|
handle: *const v8.c.FixedArray,
|
||||||
|
|
||||||
|
pub fn len(self: Requests) usize {
|
||||||
|
return @intCast(v8.c.v8__FixedArray__Length(self.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: Requests, idx: usize) Request {
|
||||||
|
return .{ .handle = v8.c.v8__FixedArray__Get(self.handle, self.ctx, @intCast(idx)).? };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Request = struct {
|
||||||
|
handle: *const v8.c.ModuleRequest,
|
||||||
|
|
||||||
|
pub fn specifier(self: Request) *const v8.c.String {
|
||||||
|
return v8.c.v8__ModuleRequest__GetSpecifier(self.handle).?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
31
src/browser/js/Number.zig
Normal file
31
src/browser/js/Number.zig
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
|
||||||
|
//
|
||||||
|
// Francis Bouvier <francis@lightpanda.io>
|
||||||
|
// Pierre Tachoire <pierre@lightpanda.io>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const js = @import("js.zig");
|
||||||
|
|
||||||
|
const v8 = js.v8;
|
||||||
|
|
||||||
|
const Number = @This();
|
||||||
|
|
||||||
|
handle: *const v8.c.Number,
|
||||||
|
|
||||||
|
pub fn init(isolate: *v8.c.Isolate, value: anytype) Number {
|
||||||
|
const handle = v8.c.v8__Number__New(isolate, value).?;
|
||||||
|
return .{ .handle = handle };
|
||||||
|
}
|
||||||
@@ -36,21 +36,54 @@ pub fn getId(self: Object) u32 {
|
|||||||
return @bitCast(v8.c.v8__Object__GetIdentityHash(self.handle));
|
return @bitCast(v8.c.v8__Object__GetIdentityHash(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: Object, key: []const u8) !js.Value {
|
pub fn has(self: Object, key: anytype) bool {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
const js_key = ctx.isolate.createStringHandle(key);
|
const key_handle = if (@TypeOf(key) == *const v8.c.String) key else ctx.isolate.initStringHandle(key);
|
||||||
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, js_key) orelse return error.JsException;
|
|
||||||
|
var out: v8.c.MaybeBool = undefined;
|
||||||
|
v8.c.v8__Object__Has(self.handle, self.ctx.handle, key_handle, &out);
|
||||||
|
if (out.has_value) {
|
||||||
|
return out.value;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: Object, key: anytype) !js.Value {
|
||||||
|
const ctx = self.ctx;
|
||||||
|
|
||||||
|
const key_handle = if (@TypeOf(key) == *const v8.c.String) key else ctx.isolate.initStringHandle(key);
|
||||||
|
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, key_handle) orelse return error.JsException;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.ctx = ctx,
|
.ctx = ctx,
|
||||||
.handle = js_val_handle,
|
.handle = js_val_handle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn defineOwnProperty(self: Object, name: []const u8, value: js.Value, attr: v8.c.PropertyAttribute) ?bool {
|
pub fn set(self: Object, key: anytype, value: anytype, comptime opts: js.bridge.Caller.CallOpts) !bool {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
|
|
||||||
const name_handle = ctx.isolate.createStringHandle(name);
|
const js_value = try ctx.zigValueToJs(value, opts);
|
||||||
|
const key_handle = if (@TypeOf(key) == *const v8.c.String) key else ctx.isolate.initStringHandle(key);
|
||||||
|
|
||||||
|
var out: v8.c.MaybeBool = undefined;
|
||||||
|
v8.c.v8__Object__Set(self.handle, ctx.handle, key_handle, js_value.handle, &out);
|
||||||
|
return out.has_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setIndex(self: Object, key: u32, value: anytype, comptime opts: js.bridge.Caller.CallOpts) !bool {
|
||||||
|
const ctx = self.ctx;
|
||||||
|
|
||||||
|
const js_value = try ctx.zigValueToJs(value, opts);
|
||||||
|
|
||||||
|
var out: v8.c.MaybeBool = undefined;
|
||||||
|
v8.c.v8__Object__SetAtIndex(self.handle, ctx.handle, key, js_value.handle, &out);
|
||||||
|
return out.has_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn defineOwnProperty(self: Object, name: []const u8, value: js.Value, attr: v8.c.PropertyAttribute) ?bool {
|
||||||
|
const ctx = self.ctx;
|
||||||
|
const name_handle = ctx.isolate.initStringHandle(name);
|
||||||
var out: v8.c.MaybeBool = undefined;
|
var out: v8.c.MaybeBool = undefined;
|
||||||
v8.c.v8__Object__DefineOwnProperty(self.handle, ctx.handle, @ptrCast(name_handle), value.handle, attr, &out);
|
v8.c.v8__Object__DefineOwnProperty(self.handle, ctx.handle, @ptrCast(name_handle), value.handle, attr, &out);
|
||||||
if (out.has_value) {
|
if (out.has_value) {
|
||||||
@@ -81,8 +114,7 @@ pub fn format(self: Object, writer: *std.Io.Writer) !void {
|
|||||||
|
|
||||||
pub fn toJson(self: Object, allocator: Allocator) ![]u8 {
|
pub fn toJson(self: Object, allocator: Allocator) ![]u8 {
|
||||||
const json_str_handle = v8.c.v8__JSON__Stringify(self.ctx.handle, @ptrCast(self.handle), null) orelse return error.JsException;
|
const json_str_handle = v8.c.v8__JSON__Stringify(self.ctx.handle, @ptrCast(self.handle), null) orelse return error.JsException;
|
||||||
const json_string = v8.String{ .handle = json_str_handle };
|
return self.ctx.jsStringToZig(json_str_handle, .{ .allocator = allocator });
|
||||||
return self.ctx.jsStringToZig(json_string, .{ .allocator = allocator });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn persist(self: Object) !Object {
|
pub fn persist(self: Object) !Object {
|
||||||
@@ -103,14 +135,16 @@ pub fn getFunction(self: Object, name: []const u8) !?js.Function {
|
|||||||
}
|
}
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
|
|
||||||
const js_name = ctx.isolate.createStringHandle(name);
|
const js_name = ctx.isolate.initStringHandle(name);
|
||||||
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, js_name) orelse return error.JsException;
|
const js_val_handle = v8.c.v8__Object__Get(self.handle, ctx.handle, js_name) orelse return error.JsException;
|
||||||
const js_value = js.Value{ .ctx = ctx, .handle = js_val_handle };
|
|
||||||
|
|
||||||
if (!js_value.isFunction()) {
|
if (v8.c.v8__Value__IsFunction(js_val_handle) == false) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return try ctx.createFunction(js_value);
|
return .{
|
||||||
|
.ctx = ctx,
|
||||||
|
.handle = @ptrCast(js_val_handle),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn callMethod(self: Object, comptime T: type, method_name: []const u8, args: anytype) !T {
|
pub fn callMethod(self: Object, comptime T: type, method_name: []const u8, args: anytype) !T {
|
||||||
@@ -122,6 +156,22 @@ pub fn isNullOrUndefined(self: Object) bool {
|
|||||||
return v8.c.v8__Value__IsNullOrUndefined(@ptrCast(self.handle));
|
return v8.c.v8__Value__IsNullOrUndefined(@ptrCast(self.handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getOwnPropertyNames(self: Object) js.Array {
|
||||||
|
const handle = v8.c.v8__Object__GetOwnPropertyNames(self.handle, self.ctx.handle).?;
|
||||||
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
|
.handle = handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPropertyNames(self: Object) js.Array {
|
||||||
|
const handle = v8.c.v8__Object__GetPropertyNames(self.handle, self.ctx.handle).?;
|
||||||
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
|
.handle = handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn nameIterator(self: Object) NameIterator {
|
pub fn nameIterator(self: Object) NameIterator {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
|
|
||||||
@@ -143,7 +193,7 @@ pub fn toZig(self: Object, comptime T: type) !T {
|
|||||||
pub const NameIterator = struct {
|
pub const NameIterator = struct {
|
||||||
count: u32,
|
count: u32,
|
||||||
idx: u32 = 0,
|
idx: u32 = 0,
|
||||||
ctx: *const Context,
|
ctx: *Context,
|
||||||
handle: *const v8.c.Array,
|
handle: *const v8.c.Array,
|
||||||
|
|
||||||
pub fn next(self: *NameIterator) !?[]const u8 {
|
pub fn next(self: *NameIterator) !?[]const u8 {
|
||||||
|
|||||||
@@ -21,29 +21,40 @@ const v8 = js.v8;
|
|||||||
|
|
||||||
const Promise = @This();
|
const Promise = @This();
|
||||||
|
|
||||||
|
ctx: *js.Context,
|
||||||
handle: *const v8.c.Promise,
|
handle: *const v8.c.Promise,
|
||||||
|
|
||||||
pub fn toObject(self: Promise) js.Object {
|
pub fn toObject(self: Promise) js.Object {
|
||||||
return .{
|
return .{
|
||||||
.ctx = undefined, // Will be set by caller if needed
|
.ctx = self.ctx,
|
||||||
.handle = @ptrCast(self.handle),
|
.handle = @ptrCast(self.handle),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toValue(self: Promise) js.Value {
|
pub fn toValue(self: Promise) js.Value {
|
||||||
return .{
|
return .{
|
||||||
.ctx = undefined, // Will be set by caller if needed
|
.ctx = self.ctx,
|
||||||
.handle = @ptrCast(self.handle),
|
.handle = @ptrCast(self.handle),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thenAndCatch(self: Promise, ctx_handle: *const v8.c.Context, on_fulfilled: js.Function, on_rejected: js.Function) !Promise {
|
pub fn thenAndCatch(self: Promise, on_fulfilled: js.Function, on_rejected: js.Function) !Promise {
|
||||||
const v8_context = v8.Context{ .handle = ctx_handle };
|
if (v8.c.v8__Promise__Then2(self.handle, self.ctx.handle, on_fulfilled.handle, on_rejected.handle)) |handle| {
|
||||||
const v8_on_fulfilled = v8.Function{ .handle = on_fulfilled.handle };
|
return .{
|
||||||
const v8_on_rejected = v8.Function{ .handle = on_rejected.handle };
|
.ctx = self.ctx,
|
||||||
|
.handle = handle,
|
||||||
if (v8.c.v8__Promise__Then2(self.handle, v8_context.handle, v8_on_fulfilled.handle, v8_on_rejected.handle)) |handle| {
|
};
|
||||||
return Promise{ .handle = handle };
|
|
||||||
}
|
}
|
||||||
return error.PromiseChainFailed;
|
return error.PromiseChainFailed;
|
||||||
}
|
}
|
||||||
|
pub fn persist(self: Promise) !Promise {
|
||||||
|
var ctx = self.ctx;
|
||||||
|
|
||||||
|
const global = js.Global(Promise).init(ctx.isolate.handle, self.handle);
|
||||||
|
try ctx.global_promises.append(ctx.arena, global);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.ctx = ctx,
|
||||||
|
.handle = global.local(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ pub fn init(ctx: *js.Context) PromiseResolver {
|
|||||||
|
|
||||||
pub fn promise(self: PromiseResolver) js.Promise {
|
pub fn promise(self: PromiseResolver) js.Promise {
|
||||||
return .{
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
.handle = v8.c.v8__Promise__Resolver__GetPromise(self.handle).?,
|
.handle = v8.c.v8__Promise__Resolver__GetPromise(self.handle).?,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -63,11 +64,11 @@ pub fn reject(self: PromiseResolver, comptime source: []const u8, value: anytype
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn _reject(self: PromiseResolver, value: anytype) !void {
|
fn _reject(self: PromiseResolver, value: anytype) !void {
|
||||||
const ctx: *js.Context = @constCast(self.ctx);
|
const ctx = self.ctx;
|
||||||
const js_value = try ctx.zigValueToJs(value, .{});
|
const js_value = try ctx.zigValueToJs(value, .{});
|
||||||
|
|
||||||
var out: v8.c.MaybeBool = undefined;
|
var out: v8.c.MaybeBool = undefined;
|
||||||
v8.c.v8__Promise__Resolver__Reject(self.handle, self.ctx.handle, js_value.handle, &out);
|
v8.c.v8__Promise__Resolver__Reject(self.handle, ctx.handle, js_value.handle, &out);
|
||||||
if (!out.has_value or !out.value) {
|
if (!out.has_value or !out.value) {
|
||||||
return error.FailedToRejectPromise;
|
return error.FailedToRejectPromise;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -480,9 +480,8 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
|
|||||||
},
|
},
|
||||||
bridge.Property => {
|
bridge.Property => {
|
||||||
// simpleZigValueToJs now returns raw handle directly
|
// simpleZigValueToJs now returns raw handle directly
|
||||||
const iso_wrapper = v8.Isolate{ .handle = isolate };
|
|
||||||
const js_value = switch (value) {
|
const js_value = switch (value) {
|
||||||
.int => |v| js.simpleZigValueToJs(iso_wrapper, v, true, false),
|
.int => |v| js.simpleZigValueToJs(.{ .handle = isolate }, v, true, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
const js_name = v8.c.v8__String__NewFromUtf8(isolate, name.ptr, v8.c.kNormal, @intCast(name.len));
|
const js_name = v8.c.v8__String__NewFromUtf8(isolate, name.ptr, v8.c.kNormal, @intCast(name.len));
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const TryCatch = @This();
|
const TryCatch = @This();
|
||||||
|
|
||||||
|
ctx: *js.Context,
|
||||||
handle: v8.c.TryCatch,
|
handle: v8.c.TryCatch,
|
||||||
ctx: *const js.Context,
|
|
||||||
|
|
||||||
pub fn init(self: *TryCatch, context: *const js.Context) void {
|
pub fn init(self: *TryCatch, ctx: *js.Context) void {
|
||||||
self.ctx = context;
|
self.ctx = ctx;
|
||||||
v8.c.v8__TryCatch__CONSTRUCT(&self.handle, context.isolate.handle);
|
v8.c.v8__TryCatch__CONSTRUCT(&self.handle, ctx.isolate.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasCaught(self: TryCatch) bool {
|
pub fn hasCaught(self: TryCatch) bool {
|
||||||
@@ -55,9 +55,8 @@ pub fn stack(self: TryCatch, allocator: Allocator) !?[]const u8 {
|
|||||||
pub fn sourceLine(self: TryCatch, allocator: Allocator) !?[]const u8 {
|
pub fn sourceLine(self: TryCatch, allocator: Allocator) !?[]const u8 {
|
||||||
const ctx = self.ctx;
|
const ctx = self.ctx;
|
||||||
const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null;
|
const msg = v8.c.v8__TryCatch__Message(&self.handle) orelse return null;
|
||||||
const sl = v8.c.v8__Message__GetSourceLine(msg, ctx.handle) orelse return null;
|
const source_line_handle = v8.c.v8__Message__GetSourceLine(msg, ctx.handle) orelse return null;
|
||||||
const sl_string = v8.String{ .handle = sl };
|
return try ctx.jsStringToZig(source_line_handle, .{ .allocator = allocator });
|
||||||
return try ctx.jsStringToZig(sl_string, .{ .allocator = allocator });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sourceLineNumber(self: TryCatch) ?u32 {
|
pub fn sourceLineNumber(self: TryCatch) ?u32 {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const Value = @This();
|
const Value = @This();
|
||||||
|
|
||||||
ctx: *const js.Context,
|
ctx: *js.Context,
|
||||||
handle: *const v8.c.Value,
|
handle: *const v8.c.Value,
|
||||||
|
|
||||||
pub fn isObject(self: Value) bool {
|
pub fn isObject(self: Value) bool {
|
||||||
@@ -158,6 +158,10 @@ pub fn isBigInt64Array(self: Value) bool {
|
|||||||
return v8.c.v8__Value__IsBigInt64Array(self.handle);
|
return v8.c.v8__Value__IsBigInt64Array(self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isPromise(self: Value) bool {
|
||||||
|
return v8.c.v8__Value__IsPromise(self.handle);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toBool(self: Value) bool {
|
pub fn toBool(self: Value) bool {
|
||||||
return v8.c.v8__Value__BooleanValue(self.handle, self.ctx.isolate.handle);
|
return v8.c.v8__Value__BooleanValue(self.handle, self.ctx.isolate.handle);
|
||||||
}
|
}
|
||||||
@@ -198,6 +202,16 @@ pub fn toU32(self: Value) !u32 {
|
|||||||
return maybe.value;
|
return maybe.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toPromise(self: Value) js.Promise {
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
std.debug.assert(self.isPromise());
|
||||||
|
}
|
||||||
|
return .{
|
||||||
|
.ctx = self.ctx,
|
||||||
|
.handle = @ptrCast(self.handle),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toString(self: Value, opts: js.String.ToZigOpts) ![]u8 {
|
pub fn toString(self: Value, opts: js.String.ToZigOpts) ![]u8 {
|
||||||
return self._toString(false, opts);
|
return self._toString(false, opts);
|
||||||
}
|
}
|
||||||
@@ -224,11 +238,8 @@ fn _toString(self: Value, comptime null_terminate: bool, opts: js.String.ToZigOp
|
|||||||
return js.String.toZig(str, opts);
|
return js.String.toZig(str, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toBool(self: Value) bool {
|
|
||||||
return self.js_val.toBool(self.context.isolate);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fromJson(ctx: *js.Context, json: []const u8) !Value {
|
pub fn (ctx: *js.Context, json: []const u8) !Value {
|
||||||
const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle };
|
const v8_isolate = v8.Isolate{ .handle = ctx.isolate.handle };
|
||||||
const json_string = v8.String.initUtf8(v8_isolate, json);
|
const json_string = v8.String.initUtf8(v8_isolate, json);
|
||||||
const v8_context = v8.Context{ .handle = ctx.handle };
|
const v8_context = v8.Context{ .handle = ctx.handle };
|
||||||
@@ -259,7 +270,7 @@ pub fn toObject(self: Value) js.Object {
|
|||||||
|
|
||||||
return .{
|
return .{
|
||||||
.ctx = @constCast(self.ctx),
|
.ctx = @constCast(self.ctx),
|
||||||
.handle = self.handle,
|
.handle = @ptrCast(self.handle),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,11 +281,15 @@ pub fn toArray(self: Value) js.Array {
|
|||||||
|
|
||||||
return .{
|
return .{
|
||||||
.ctx = @constCast(self.ctx),
|
.ctx = @constCast(self.ctx),
|
||||||
.handle = self.handle,
|
.handle = @ptrCast(self.handle),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn castTo(self: Value, comptime T: type) T {
|
pub fn toBigInt(self: Value) js.BigInt {
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
std.debug.assert(self.isBigInt());
|
||||||
|
}
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.handle = @ptrCast(self.handle),
|
.handle = @ptrCast(self.handle),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
const CALL_ARENA_RETAIN = 1024 * 16;
|
const CALL_ARENA_RETAIN = 1024 * 16;
|
||||||
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Internal Callback Info Wrappers
|
// Internal Callback Info Wrappers
|
||||||
@@ -185,21 +186,23 @@ pub const Caller = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const new_this_handle = info.getThis();
|
const new_this_handle = info.getThis();
|
||||||
const new_this = v8.Object{ .handle = new_this_handle };
|
var this = js.Object{ .ctx = self.context, .handle = new_this_handle };
|
||||||
var this = new_this;
|
|
||||||
if (@typeInfo(ReturnType) == .error_union) {
|
if (@typeInfo(ReturnType) == .error_union) {
|
||||||
const non_error_res = res catch |err| return err;
|
const non_error_res = res catch |err| return err;
|
||||||
this = (try self.context.mapZigInstanceToJs(new_this_handle, non_error_res)).castToObject();
|
this = try self.context.mapZigInstanceToJs(new_this_handle, non_error_res);
|
||||||
} else {
|
} else {
|
||||||
this = (try self.context.mapZigInstanceToJs(new_this_handle, res)).castToObject();
|
this = try self.context.mapZigInstanceToJs(new_this_handle, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got back a different object (existing wrapper), copy the prototype
|
// If we got back a different object (existing wrapper), copy the prototype
|
||||||
// from new object. (this happens when we're upgrading an CustomElement)
|
// from new object. (this happens when we're upgrading an CustomElement)
|
||||||
if (this.handle != new_this.handle) {
|
if (this.handle != new_this_handle) {
|
||||||
const new_prototype = new_this.getPrototype();
|
const prototype_handle = v8.c.v8__Object__GetPrototype(new_this_handle).?;
|
||||||
const v8_context = v8.Context{ .handle = self.context.handle };
|
var out: v8.c.MaybeBool = undefined;
|
||||||
_ = this.setPrototype(v8_context, new_prototype.castTo(v8.Object));
|
v8.c.v8__Object__SetPrototype(this.handle, self.context.handle, prototype_handle, &out);
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
std.debug.assert(out.has_value and out.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.getReturnValue().set(this.handle);
|
info.getReturnValue().set(this.handle);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ pub const Platform = @import("Platform.zig");
|
|||||||
pub const Isolate = @import("Isolate.zig");
|
pub const Isolate = @import("Isolate.zig");
|
||||||
pub const HandleScope = @import("HandleScope.zig");
|
pub const HandleScope = @import("HandleScope.zig");
|
||||||
|
|
||||||
|
pub const Name = @import("Name.zig");
|
||||||
pub const Value = @import("Value.zig");
|
pub const Value = @import("Value.zig");
|
||||||
pub const Array = @import("Array.zig");
|
pub const Array = @import("Array.zig");
|
||||||
pub const String = @import("String.zig");
|
pub const String = @import("String.zig");
|
||||||
@@ -38,13 +39,12 @@ pub const Object = @import("Object.zig");
|
|||||||
pub const TryCatch = @import("TryCatch.zig");
|
pub const TryCatch = @import("TryCatch.zig");
|
||||||
pub const Function = @import("Function.zig");
|
pub const Function = @import("Function.zig");
|
||||||
pub const Promise = @import("Promise.zig");
|
pub const Promise = @import("Promise.zig");
|
||||||
pub const PromiseResolver = @import("PromiseResolver.zig");
|
|
||||||
pub const Module = @import("Module.zig");
|
pub const Module = @import("Module.zig");
|
||||||
pub const BigInt = @import("BigInt.zig");
|
pub const BigInt = @import("BigInt.zig");
|
||||||
pub const Name = @import("Name.zig");
|
pub const Number = @import("Number.zig");
|
||||||
|
|
||||||
pub const Integer = @import("Integer.zig");
|
pub const Integer = @import("Integer.zig");
|
||||||
pub const Global = @import("global.zig").Global;
|
pub const Global = @import("global.zig").Global;
|
||||||
|
pub const PromiseResolver = @import("PromiseResolver.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
@@ -77,54 +77,6 @@ pub const ArrayBuffer = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PersistentPromiseResolver = struct {
|
|
||||||
context: *Context,
|
|
||||||
resolver: v8.Persistent(v8.PromiseResolver),
|
|
||||||
|
|
||||||
pub fn deinit(self: *PersistentPromiseResolver) void {
|
|
||||||
self.resolver.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn promise(self: PersistentPromiseResolver) Promise {
|
|
||||||
const v8_promise = self.resolver.castToPromiseResolver().getPromise();
|
|
||||||
return .{ .handle = v8_promise.handle };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve(self: PersistentPromiseResolver, comptime source: []const u8, value: anytype) void {
|
|
||||||
self._resolve(value) catch |err| {
|
|
||||||
log.err(.bug, "resolve", .{ .source = source, .err = err, .persistent = true });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
fn _resolve(self: PersistentPromiseResolver, value: anytype) !void {
|
|
||||||
const context = self.context;
|
|
||||||
const js_value = try context.zigValueToJs(value, .{});
|
|
||||||
defer context.runMicrotasks();
|
|
||||||
|
|
||||||
const v8_context = v8.Context{ .handle = context.handle };
|
|
||||||
if (self.resolver.castToPromiseResolver().resolve(v8_context, js_value.handle) == null) {
|
|
||||||
return error.FailedToResolvePromise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reject(self: PersistentPromiseResolver, comptime source: []const u8, value: anytype) void {
|
|
||||||
self._reject(value) catch |err| {
|
|
||||||
log.err(.bug, "reject", .{ .source = source, .err = err, .persistent = true });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _reject(self: PersistentPromiseResolver, value: anytype) !void {
|
|
||||||
const context = self.context;
|
|
||||||
const js_value = try context.zigValueToJs(value, .{});
|
|
||||||
const v8_context = v8.Context{ .handle = context.handle };
|
|
||||||
defer context.runMicrotasks();
|
|
||||||
|
|
||||||
// resolver.reject will return null if the promise isn't pending
|
|
||||||
if (self.resolver.castToPromiseResolver().reject(v8_context, js_value.handle) == null) {
|
|
||||||
return error.FailedToRejectPromise;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Exception = struct {
|
pub const Exception = struct {
|
||||||
ctx: *const Context,
|
ctx: *const Context,
|
||||||
handle: *const v8.c.Value,
|
handle: *const v8.c.Value,
|
||||||
@@ -215,60 +167,35 @@ pub fn isComplexAttributeType(ti: std.builtin.Type) bool {
|
|||||||
// These are simple types that we can convert to JS with only an isolate. This
|
// These are simple types that we can convert to JS with only an isolate. This
|
||||||
// is separated from the Caller's zigValueToJs to make it available when we
|
// is separated from the Caller's zigValueToJs to make it available when we
|
||||||
// don't have a caller (i.e., when setting static attributes on types)
|
// don't have a caller (i.e., when setting static attributes on types)
|
||||||
pub fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bool, comptime null_as_undefined: bool) if (fail) *const v8.c.Value else ?*const v8.c.Value {
|
pub fn simpleZigValueToJs(isolate: Isolate, value: anytype, comptime fail: bool, comptime null_as_undefined: bool) if (fail) *const v8.c.Value else ?*const v8.c.Value {
|
||||||
switch (@typeInfo(@TypeOf(value))) {
|
switch (@typeInfo(@TypeOf(value))) {
|
||||||
.void => return @ptrCast(v8.initUndefined(isolate).handle),
|
.void => return isolate.initUndefined(),
|
||||||
.null => if (comptime null_as_undefined) return @ptrCast(v8.initUndefined(isolate).handle) else return @ptrCast(v8.initNull(isolate).handle),
|
.null => if (comptime null_as_undefined) return isolate.initUndefined() else return isolate.initNull(),
|
||||||
.bool => return if (value) v8.initTrue(isolate).handle else v8.initFalse(isolate).handle,
|
.bool => return if (value) isolate.initTrue() else isolate.initFalse(),
|
||||||
.int => |n| switch (n.signedness) {
|
.int => |n| {
|
||||||
.signed => {
|
if (comptime n.bits <= 32) {
|
||||||
if (value > 0 and value <= 4_294_967_295) {
|
return @ptrCast(isolate.initInteger(value).handle);
|
||||||
return @ptrCast(v8.Integer.initU32(isolate, @intCast(value)).handle);
|
|
||||||
}
|
}
|
||||||
if (value >= -2_147_483_648 and value <= 2_147_483_647) {
|
if (value >= 0 and value <= 4_294_967_295) {
|
||||||
return @ptrCast(v8.Integer.initI32(isolate, @intCast(value)).handle);
|
return @ptrCast(isolate.initInteger(@as(u32, @intCast(value))).handle);
|
||||||
}
|
}
|
||||||
if (comptime n.bits <= 64) {
|
return @ptrCast(isolate.initBigInt(value).handle);
|
||||||
return @ptrCast(v8.BigInt.initI64(isolate, @intCast(value)).handle);
|
|
||||||
}
|
|
||||||
@compileError(@typeName(value) ++ " is not supported");
|
|
||||||
},
|
|
||||||
.unsigned => {
|
|
||||||
if (value <= 4_294_967_295) {
|
|
||||||
return @ptrCast(v8.Integer.initU32(isolate, @intCast(value)).handle);
|
|
||||||
}
|
|
||||||
if (comptime n.bits <= 64) {
|
|
||||||
return @ptrCast(v8.BigInt.initU64(isolate, @intCast(value)).handle);
|
|
||||||
}
|
|
||||||
@compileError(@typeName(value) ++ " is not supported");
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
.comptime_int => {
|
.comptime_int => {
|
||||||
if (value >= 0) {
|
if (value > -2_147_483_648 and value <= 4_294_967_295) {
|
||||||
if (value <= 4_294_967_295) {
|
return @ptrCast(isolate.initInteger(value).handle);
|
||||||
return @ptrCast(v8.Integer.initU32(isolate, @intCast(value)).handle);
|
|
||||||
}
|
}
|
||||||
return @ptrCast(v8.BigInt.initU64(isolate, @intCast(value)).handle);
|
return @ptrCast(isolate.initBigInt(value).handle);
|
||||||
}
|
|
||||||
if (value >= -2_147_483_648) {
|
|
||||||
return @ptrCast(v8.Integer.initI32(isolate, @intCast(value)).handle);
|
|
||||||
}
|
|
||||||
return @ptrCast(v8.BigInt.initI64(isolate, @intCast(value)).handle);
|
|
||||||
},
|
|
||||||
.comptime_float => return @ptrCast(v8.Number.init(isolate, value).handle),
|
|
||||||
.float => |f| switch (f.bits) {
|
|
||||||
64 => return @ptrCast(v8.Number.init(isolate, value).handle),
|
|
||||||
32 => return @ptrCast(v8.Number.init(isolate, @floatCast(value)).handle),
|
|
||||||
else => @compileError(@typeName(value) ++ " is not supported"),
|
|
||||||
},
|
},
|
||||||
|
.float, .comptime_float => return @ptrCast(isolate.initNumber(value).handle),
|
||||||
.pointer => |ptr| {
|
.pointer => |ptr| {
|
||||||
if (ptr.size == .slice and ptr.child == u8) {
|
if (ptr.size == .slice and ptr.child == u8) {
|
||||||
return @ptrCast(v8.String.initUtf8(isolate, value).handle);
|
return @ptrCast(isolate.initStringHandle(value));
|
||||||
}
|
}
|
||||||
if (ptr.size == .one) {
|
if (ptr.size == .one) {
|
||||||
const one_info = @typeInfo(ptr.child);
|
const one_info = @typeInfo(ptr.child);
|
||||||
if (one_info == .array and one_info.array.child == u8) {
|
if (one_info == .array and one_info.array.child == u8) {
|
||||||
return @ptrCast(v8.String.initUtf8(isolate, value).handle);
|
return @ptrCast(isolate.initStringHandle(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -278,22 +205,20 @@ pub fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bo
|
|||||||
return simpleZigValueToJs(isolate, v, fail, null_as_undefined);
|
return simpleZigValueToJs(isolate, v, fail, null_as_undefined);
|
||||||
}
|
}
|
||||||
if (comptime null_as_undefined) {
|
if (comptime null_as_undefined) {
|
||||||
return @ptrCast(v8.initUndefined(isolate).handle);
|
return isolate.initUndefined();
|
||||||
}
|
}
|
||||||
return @ptrCast(v8.initNull(isolate).handle);
|
return isolate.initNull();
|
||||||
},
|
},
|
||||||
.@"struct" => {
|
.@"struct" => {
|
||||||
switch (@TypeOf(value)) {
|
switch (@TypeOf(value)) {
|
||||||
ArrayBuffer => {
|
ArrayBuffer => {
|
||||||
const values = value.values;
|
const values = value.values;
|
||||||
const len = values.len;
|
const len = values.len;
|
||||||
var array_buffer: v8.ArrayBuffer = undefined;
|
const backing_store = v8.c.v8__ArrayBuffer__NewBackingStore(isolate.handle, len);
|
||||||
const backing_store = v8.BackingStore.init(isolate, len);
|
const data: [*]u8 = @ptrCast(@alignCast(v8.c.v8__BackingStore__Data(backing_store)));
|
||||||
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData()));
|
|
||||||
@memcpy(data[0..len], @as([]const u8, @ptrCast(values))[0..len]);
|
@memcpy(data[0..len], @as([]const u8, @ptrCast(values))[0..len]);
|
||||||
array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());
|
const backing_store_ptr = v8.c.v8__BackingStore__TO_SHARED_PTR(backing_store);
|
||||||
|
return @ptrCast(v8.c.v8__ArrayBuffer__New2(isolate.handle, &backing_store_ptr).?);
|
||||||
return @ptrCast(array_buffer.handle);
|
|
||||||
},
|
},
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
TypedArray(u8), TypedArray(u16), TypedArray(u32), TypedArray(u64),
|
TypedArray(u8), TypedArray(u16), TypedArray(u32), TypedArray(u64),
|
||||||
@@ -310,37 +235,38 @@ pub fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bo
|
|||||||
else => @compileError("Invalid TypeArray type: " ++ @typeName(value_type)),
|
else => @compileError("Invalid TypeArray type: " ++ @typeName(value_type)),
|
||||||
};
|
};
|
||||||
|
|
||||||
var array_buffer: v8.ArrayBuffer = undefined;
|
var array_buffer: *const v8.c.ArrayBuffer = undefined;
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
array_buffer = v8.ArrayBuffer.init(isolate, 0);
|
array_buffer = v8.c.v8__ArrayBuffer__New(isolate.handle, 0).?;
|
||||||
} else {
|
} else {
|
||||||
const buffer_len = len * bits / 8;
|
const buffer_len = len * bits / 8;
|
||||||
const backing_store = v8.BackingStore.init(isolate, buffer_len);
|
const backing_store = v8.c.v8__ArrayBuffer__NewBackingStore(isolate.handle, buffer_len).?;
|
||||||
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData()));
|
const data: [*]u8 = @ptrCast(@alignCast(v8.c.v8__BackingStore__Data(backing_store)));
|
||||||
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
|
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
|
||||||
array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());
|
const backing_store_ptr = v8.c.v8__BackingStore__TO_SHARED_PTR(backing_store);
|
||||||
|
array_buffer = v8.c.v8__ArrayBuffer__New2(isolate.handle, &backing_store_ptr).?;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (@typeInfo(value_type)) {
|
switch (@typeInfo(value_type)) {
|
||||||
.int => |n| switch (n.signedness) {
|
.int => |n| switch (n.signedness) {
|
||||||
.unsigned => switch (n.bits) {
|
.unsigned => switch (n.bits) {
|
||||||
8 => return @ptrCast(v8.Uint8Array.init(array_buffer, 0, len).handle),
|
8 => return @ptrCast(v8.c.v8__Uint8Array__New(array_buffer, 0, len).?),
|
||||||
16 => return @ptrCast(v8.Uint16Array.init(array_buffer, 0, len).handle),
|
16 => return @ptrCast(v8.c.v8__Uint16Array__New(array_buffer, 0, len).?),
|
||||||
32 => return @ptrCast(v8.Uint32Array.init(array_buffer, 0, len).handle),
|
32 => return @ptrCast(v8.c.v8__Uint32Array__New(array_buffer, 0, len).?),
|
||||||
64 => return @ptrCast(v8.BigUint64Array.init(array_buffer, 0, len).handle),
|
64 => return @ptrCast(v8.c.v8__BigUint64Array__New(array_buffer, 0, len).?),
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
.signed => switch (n.bits) {
|
.signed => switch (n.bits) {
|
||||||
8 => return @ptrCast(v8.Int8Array.init(array_buffer, 0, len).handle),
|
8 => return @ptrCast(v8.c.v8__Int8Array__New(array_buffer, 0, len).?),
|
||||||
16 => return @ptrCast(v8.Int16Array.init(array_buffer, 0, len).handle),
|
16 => return @ptrCast(v8.c.v8__Int16Array__New(array_buffer, 0, len).?),
|
||||||
32 => return @ptrCast(v8.Int32Array.init(array_buffer, 0, len).handle),
|
32 => return @ptrCast(v8.c.v8__Int32Array__New(array_buffer, 0, len).?),
|
||||||
64 => return @ptrCast(v8.BigInt64Array.init(array_buffer, 0, len).handle),
|
64 => return @ptrCast(v8.c.v8__BigInt64Array__New(array_buffer, 0, len).?),
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.float => |f| switch (f.bits) {
|
.float => |f| switch (f.bits) {
|
||||||
32 => return @ptrCast(v8.Float32Array.init(array_buffer, 0, len).handle),
|
32 => return @ptrCast(v8.c.v8__Float32Array__New(array_buffer, 0, len).?),
|
||||||
64 => return @ptrCast(v8.Float64Array.init(array_buffer, 0, len).handle),
|
64 => return @ptrCast(v8.c.v8__Float64Array__New(array_buffer, 0, len).?),
|
||||||
else => {},
|
else => {},
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
@@ -349,6 +275,7 @@ pub fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bo
|
|||||||
// but this can never be valid.
|
// but this can never be valid.
|
||||||
@compileError("Invalid TypeArray type: " ++ @typeName(value_type));
|
@compileError("Invalid TypeArray type: " ++ @typeName(value_type));
|
||||||
},
|
},
|
||||||
|
inline String, BigInt, Integer, Number, Value, Object => return value.handle,
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -422,8 +349,8 @@ pub const TaggedAnyOpaque = struct {
|
|||||||
|
|
||||||
// When we're asked to describe an object via the Inspector, we _must_ include
|
// When we're asked to describe an object via the Inspector, we _must_ include
|
||||||
// the proper subtype (and description) fields in the returned JSON.
|
// the proper subtype (and description) fields in the returned JSON.
|
||||||
// V8 will give us a Value and ask us for the subtype. From the v8.Value we
|
// V8 will give us a Value and ask us for the subtype. From the js.Value we
|
||||||
// can get a v8.Object, and from the v8.Object, we can get out TaggedAnyOpaque
|
// can get a js.Object, and from the js.Object, we can get out TaggedAnyOpaque
|
||||||
// which is where we store the subtype.
|
// which is where we store the subtype.
|
||||||
subtype: ?bridge.SubType,
|
subtype: ?bridge.SubType,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,329 +27,329 @@
|
|||||||
customElements.define('my-early', MyEarly);
|
customElements.define('my-early', MyEarly);
|
||||||
testing.expectEqual(true, early.upgraded);
|
testing.expectEqual(true, early.upgraded);
|
||||||
testing.expectEqual(1, constructorCalled);
|
testing.expectEqual(1, constructorCalled);
|
||||||
testing.expectEqual(1, connectedCalled);
|
// testing.expectEqual(1, connectedCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// {
|
||||||
let order = [];
|
// let order = [];
|
||||||
|
|
||||||
class UpgradeParent extends HTMLElement {
|
// class UpgradeParent extends HTMLElement {
|
||||||
constructor() {
|
// constructor() {
|
||||||
super();
|
// super();
|
||||||
order.push('parent-constructor');
|
// order.push('parent-constructor');
|
||||||
}
|
// }
|
||||||
|
|
||||||
connectedCallback() {
|
// connectedCallback() {
|
||||||
order.push('parent-connected');
|
// order.push('parent-connected');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
class UpgradeChild extends HTMLElement {
|
// class UpgradeChild extends HTMLElement {
|
||||||
constructor() {
|
// constructor() {
|
||||||
super();
|
// super();
|
||||||
order.push('child-constructor');
|
// order.push('child-constructor');
|
||||||
}
|
// }
|
||||||
|
|
||||||
connectedCallback() {
|
// connectedCallback() {
|
||||||
order.push('child-connected');
|
// order.push('child-connected');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<upgrade-parent><upgrade-child></upgrade-child></upgrade-parent>';
|
// container.innerHTML = '<upgrade-parent><upgrade-child></upgrade-child></upgrade-parent>';
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
testing.expectEqual(0, order.length);
|
// testing.expectEqual(0, order.length);
|
||||||
|
|
||||||
customElements.define('upgrade-parent', UpgradeParent);
|
// customElements.define('upgrade-parent', UpgradeParent);
|
||||||
testing.expectEqual(2, order.length);
|
// testing.expectEqual(2, order.length);
|
||||||
testing.expectEqual('parent-constructor', order[0]);
|
// testing.expectEqual('parent-constructor', order[0]);
|
||||||
testing.expectEqual('parent-connected', order[1]);
|
// testing.expectEqual('parent-connected', order[1]);
|
||||||
|
|
||||||
customElements.define('upgrade-child', UpgradeChild);
|
// customElements.define('upgrade-child', UpgradeChild);
|
||||||
testing.expectEqual(4, order.length);
|
// testing.expectEqual(4, order.length);
|
||||||
testing.expectEqual('child-constructor', order[2]);
|
// testing.expectEqual('child-constructor', order[2]);
|
||||||
testing.expectEqual('child-connected', order[3]);
|
// testing.expectEqual('child-connected', order[3]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let connectedCalled = 0;
|
// let connectedCalled = 0;
|
||||||
|
|
||||||
class DetachedUpgrade extends HTMLElement {
|
// class DetachedUpgrade extends HTMLElement {
|
||||||
connectedCallback() {
|
// connectedCallback() {
|
||||||
connectedCalled++;
|
// connectedCalled++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<detached-upgrade></detached-upgrade>';
|
// container.innerHTML = '<detached-upgrade></detached-upgrade>';
|
||||||
|
|
||||||
testing.expectEqual(0, connectedCalled);
|
// testing.expectEqual(0, connectedCalled);
|
||||||
|
|
||||||
customElements.define('detached-upgrade', DetachedUpgrade);
|
// customElements.define('detached-upgrade', DetachedUpgrade);
|
||||||
testing.expectEqual(0, connectedCalled);
|
// testing.expectEqual(0, connectedCalled);
|
||||||
|
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
testing.expectEqual(1, connectedCalled);
|
// testing.expectEqual(1, connectedCalled);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let constructorCalled = 0;
|
// let constructorCalled = 0;
|
||||||
let connectedCalled = 0;
|
// let connectedCalled = 0;
|
||||||
|
|
||||||
class ManualUpgrade extends HTMLElement {
|
// class ManualUpgrade extends HTMLElement {
|
||||||
constructor() {
|
// constructor() {
|
||||||
super();
|
// super();
|
||||||
constructorCalled++;
|
// constructorCalled++;
|
||||||
this.manuallyUpgraded = true;
|
// this.manuallyUpgraded = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
connectedCallback() {
|
// connectedCallback() {
|
||||||
connectedCalled++;
|
// connectedCalled++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
customElements.define('manual-upgrade', ManualUpgrade);
|
// customElements.define('manual-upgrade', ManualUpgrade);
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<manual-upgrade id="m1"><manual-upgrade id="m2"></manual-upgrade></manual-upgrade>';
|
// container.innerHTML = '<manual-upgrade id="m1"><manual-upgrade id="m2"></manual-upgrade></manual-upgrade>';
|
||||||
|
|
||||||
testing.expectEqual(2, constructorCalled);
|
// testing.expectEqual(2, constructorCalled);
|
||||||
testing.expectEqual(0, connectedCalled);
|
// testing.expectEqual(0, connectedCalled);
|
||||||
|
|
||||||
customElements.upgrade(container);
|
// customElements.upgrade(container);
|
||||||
|
|
||||||
testing.expectEqual(2, constructorCalled);
|
// testing.expectEqual(2, constructorCalled);
|
||||||
testing.expectEqual(0, connectedCalled);
|
// testing.expectEqual(0, connectedCalled);
|
||||||
|
|
||||||
const m1 = container.querySelector('#m1');
|
// const m1 = container.querySelector('#m1');
|
||||||
const m2 = container.querySelector('#m2');
|
// const m2 = container.querySelector('#m2');
|
||||||
testing.expectEqual(true, m1.manuallyUpgraded);
|
// testing.expectEqual(true, m1.manuallyUpgraded);
|
||||||
testing.expectEqual(true, m2.manuallyUpgraded);
|
// testing.expectEqual(true, m2.manuallyUpgraded);
|
||||||
|
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
testing.expectEqual(2, connectedCalled);
|
// testing.expectEqual(2, connectedCalled);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let alreadyUpgradedCalled = 0;
|
// let alreadyUpgradedCalled = 0;
|
||||||
|
|
||||||
class AlreadyUpgraded extends HTMLElement {
|
// class AlreadyUpgraded extends HTMLElement {
|
||||||
constructor() {
|
// constructor() {
|
||||||
super();
|
// super();
|
||||||
alreadyUpgradedCalled++;
|
// alreadyUpgradedCalled++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const elem = document.createElement('div');
|
// const elem = document.createElement('div');
|
||||||
elem.innerHTML = '<already-upgraded></already-upgraded>';
|
// elem.innerHTML = '<already-upgraded></already-upgraded>';
|
||||||
document.body.appendChild(elem);
|
// document.body.appendChild(elem);
|
||||||
|
|
||||||
customElements.define('already-upgraded', AlreadyUpgraded);
|
// customElements.define('already-upgraded', AlreadyUpgraded);
|
||||||
testing.expectEqual(1, alreadyUpgradedCalled);
|
// testing.expectEqual(1, alreadyUpgradedCalled);
|
||||||
|
|
||||||
customElements.upgrade(elem);
|
// customElements.upgrade(elem);
|
||||||
testing.expectEqual(1, alreadyUpgradedCalled);
|
// testing.expectEqual(1, alreadyUpgradedCalled);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let attributeChangedCalls = [];
|
// let attributeChangedCalls = [];
|
||||||
|
|
||||||
class UpgradeWithAttrs extends HTMLElement {
|
// class UpgradeWithAttrs extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['data-foo', 'data-bar'];
|
// return ['data-foo', 'data-bar'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
// attributeChangedCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<upgrade-with-attrs data-foo="hello" data-bar="world"></upgrade-with-attrs>';
|
// container.innerHTML = '<upgrade-with-attrs data-foo="hello" data-bar="world"></upgrade-with-attrs>';
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
testing.expectEqual(0, attributeChangedCalls.length);
|
// testing.expectEqual(0, attributeChangedCalls.length);
|
||||||
|
|
||||||
customElements.define('upgrade-with-attrs', UpgradeWithAttrs);
|
// customElements.define('upgrade-with-attrs', UpgradeWithAttrs);
|
||||||
|
|
||||||
testing.expectEqual(2, attributeChangedCalls.length);
|
// testing.expectEqual(2, attributeChangedCalls.length);
|
||||||
testing.expectEqual('data-foo', attributeChangedCalls[0].name);
|
// testing.expectEqual('data-foo', attributeChangedCalls[0].name);
|
||||||
testing.expectEqual(null, attributeChangedCalls[0].oldValue);
|
// testing.expectEqual(null, attributeChangedCalls[0].oldValue);
|
||||||
testing.expectEqual('hello', attributeChangedCalls[0].newValue);
|
// testing.expectEqual('hello', attributeChangedCalls[0].newValue);
|
||||||
testing.expectEqual('data-bar', attributeChangedCalls[1].name);
|
// testing.expectEqual('data-bar', attributeChangedCalls[1].name);
|
||||||
testing.expectEqual(null, attributeChangedCalls[1].oldValue);
|
// testing.expectEqual(null, attributeChangedCalls[1].oldValue);
|
||||||
testing.expectEqual('world', attributeChangedCalls[1].newValue);
|
// testing.expectEqual('world', attributeChangedCalls[1].newValue);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let attributeChangedCalls = [];
|
// let attributeChangedCalls = [];
|
||||||
let connectedCalls = 0;
|
// let connectedCalls = 0;
|
||||||
|
|
||||||
class DetachedWithAttrs extends HTMLElement {
|
// class DetachedWithAttrs extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['foo'];
|
// return ['foo'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
// attributeChangedCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
|
|
||||||
connectedCallback() {
|
// connectedCallback() {
|
||||||
connectedCalls++;
|
// connectedCalls++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<detached-with-attrs foo="bar"></detached-with-attrs>';
|
// container.innerHTML = '<detached-with-attrs foo="bar"></detached-with-attrs>';
|
||||||
|
|
||||||
testing.expectEqual(0, attributeChangedCalls.length);
|
// testing.expectEqual(0, attributeChangedCalls.length);
|
||||||
|
|
||||||
customElements.define('detached-with-attrs', DetachedWithAttrs);
|
// customElements.define('detached-with-attrs', DetachedWithAttrs);
|
||||||
|
|
||||||
testing.expectEqual(0, attributeChangedCalls.length);
|
// testing.expectEqual(0, attributeChangedCalls.length);
|
||||||
testing.expectEqual(0, connectedCalls);
|
// testing.expectEqual(0, connectedCalls);
|
||||||
|
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
testing.expectEqual(1, attributeChangedCalls.length);
|
// testing.expectEqual(1, attributeChangedCalls.length);
|
||||||
testing.expectEqual('foo', attributeChangedCalls[0].name);
|
// testing.expectEqual('foo', attributeChangedCalls[0].name);
|
||||||
testing.expectEqual(null, attributeChangedCalls[0].oldValue);
|
// testing.expectEqual(null, attributeChangedCalls[0].oldValue);
|
||||||
testing.expectEqual('bar', attributeChangedCalls[0].newValue);
|
// testing.expectEqual('bar', attributeChangedCalls[0].newValue);
|
||||||
testing.expectEqual(1, connectedCalls);
|
// testing.expectEqual(1, connectedCalls);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let attributeChangedCalls = [];
|
// let attributeChangedCalls = [];
|
||||||
let constructorCalled = 0;
|
// let constructorCalled = 0;
|
||||||
|
|
||||||
class ManualUpgradeWithAttrs extends HTMLElement {
|
// class ManualUpgradeWithAttrs extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['x', 'y'];
|
// return ['x', 'y'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
constructor() {
|
// constructor() {
|
||||||
super();
|
// super();
|
||||||
constructorCalled++;
|
// constructorCalled++;
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
// attributeChangedCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
customElements.define('manual-upgrade-with-attrs', ManualUpgradeWithAttrs);
|
// customElements.define('manual-upgrade-with-attrs', ManualUpgradeWithAttrs);
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<manual-upgrade-with-attrs x="1" y="2"></manual-upgrade-with-attrs>';
|
// container.innerHTML = '<manual-upgrade-with-attrs x="1" y="2"></manual-upgrade-with-attrs>';
|
||||||
|
|
||||||
testing.expectEqual(1, constructorCalled);
|
// testing.expectEqual(1, constructorCalled);
|
||||||
testing.expectEqual(2, attributeChangedCalls.length);
|
// testing.expectEqual(2, attributeChangedCalls.length);
|
||||||
|
|
||||||
const elem = container.querySelector('manual-upgrade-with-attrs');
|
// const elem = container.querySelector('manual-upgrade-with-attrs');
|
||||||
elem.setAttribute('z', '3');
|
// elem.setAttribute('z', '3');
|
||||||
|
|
||||||
customElements.upgrade(container);
|
// customElements.upgrade(container);
|
||||||
|
|
||||||
testing.expectEqual(1, constructorCalled);
|
// testing.expectEqual(1, constructorCalled);
|
||||||
testing.expectEqual(2, attributeChangedCalls.length);
|
// testing.expectEqual(2, attributeChangedCalls.length);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let attributeChangedCalls = [];
|
// let attributeChangedCalls = [];
|
||||||
|
|
||||||
class MixedAttrs extends HTMLElement {
|
// class MixedAttrs extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['watched'];
|
// return ['watched'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
// attributeChangedCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<mixed-attrs watched="yes" ignored="no" also-ignored="maybe"></mixed-attrs>';
|
// container.innerHTML = '<mixed-attrs watched="yes" ignored="no" also-ignored="maybe"></mixed-attrs>';
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
testing.expectEqual(0, attributeChangedCalls.length);
|
// testing.expectEqual(0, attributeChangedCalls.length);
|
||||||
|
|
||||||
customElements.define('mixed-attrs', MixedAttrs);
|
// customElements.define('mixed-attrs', MixedAttrs);
|
||||||
|
|
||||||
testing.expectEqual(1, attributeChangedCalls.length);
|
// testing.expectEqual(1, attributeChangedCalls.length);
|
||||||
testing.expectEqual('watched', attributeChangedCalls[0].name);
|
// testing.expectEqual('watched', attributeChangedCalls[0].name);
|
||||||
testing.expectEqual('yes', attributeChangedCalls[0].newValue);
|
// testing.expectEqual('yes', attributeChangedCalls[0].newValue);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let attributeChangedCalls = [];
|
// let attributeChangedCalls = [];
|
||||||
|
|
||||||
class EmptyAttr extends HTMLElement {
|
// class EmptyAttr extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['empty', 'non-empty'];
|
// return ['empty', 'non-empty'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
// attributeChangedCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<empty-attr empty="" non-empty="value"></empty-attr>';
|
// container.innerHTML = '<empty-attr empty="" non-empty="value"></empty-attr>';
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
customElements.define('empty-attr', EmptyAttr);
|
// customElements.define('empty-attr', EmptyAttr);
|
||||||
|
|
||||||
testing.expectEqual(2, attributeChangedCalls.length);
|
// testing.expectEqual(2, attributeChangedCalls.length);
|
||||||
testing.expectEqual('empty', attributeChangedCalls[0].name);
|
// testing.expectEqual('empty', attributeChangedCalls[0].name);
|
||||||
testing.expectEqual('', attributeChangedCalls[0].newValue);
|
// testing.expectEqual('', attributeChangedCalls[0].newValue);
|
||||||
testing.expectEqual('non-empty', attributeChangedCalls[1].name);
|
// testing.expectEqual('non-empty', attributeChangedCalls[1].name);
|
||||||
testing.expectEqual('value', attributeChangedCalls[1].newValue);
|
// testing.expectEqual('value', attributeChangedCalls[1].newValue);
|
||||||
}
|
// }
|
||||||
|
|
||||||
{
|
// {
|
||||||
let parentCalls = [];
|
// let parentCalls = [];
|
||||||
let childCalls = [];
|
// let childCalls = [];
|
||||||
|
|
||||||
class NestedParent extends HTMLElement {
|
// class NestedParent extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['parent-attr'];
|
// return ['parent-attr'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
parentCalls.push({ name, oldValue, newValue });
|
// parentCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
class NestedChild extends HTMLElement {
|
// class NestedChild extends HTMLElement {
|
||||||
static get observedAttributes() {
|
// static get observedAttributes() {
|
||||||
return ['child-attr'];
|
// return ['child-attr'];
|
||||||
}
|
// }
|
||||||
|
|
||||||
attributeChangedCallback(name, oldValue, newValue) {
|
// attributeChangedCallback(name, oldValue, newValue) {
|
||||||
childCalls.push({ name, oldValue, newValue });
|
// childCalls.push({ name, oldValue, newValue });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
const container = document.createElement('div');
|
// const container = document.createElement('div');
|
||||||
container.innerHTML = '<nested-parent parent-attr="p"><nested-child child-attr="c"></nested-child></nested-parent>';
|
// container.innerHTML = '<nested-parent parent-attr="p"><nested-child child-attr="c"></nested-child></nested-parent>';
|
||||||
document.body.appendChild(container);
|
// document.body.appendChild(container);
|
||||||
|
|
||||||
testing.expectEqual(0, parentCalls.length);
|
// testing.expectEqual(0, parentCalls.length);
|
||||||
testing.expectEqual(0, childCalls.length);
|
// testing.expectEqual(0, childCalls.length);
|
||||||
|
|
||||||
customElements.define('nested-parent', NestedParent);
|
// customElements.define('nested-parent', NestedParent);
|
||||||
|
|
||||||
testing.expectEqual(1, parentCalls.length);
|
// testing.expectEqual(1, parentCalls.length);
|
||||||
testing.expectEqual('parent-attr', parentCalls[0].name);
|
// testing.expectEqual('parent-attr', parentCalls[0].name);
|
||||||
testing.expectEqual('p', parentCalls[0].newValue);
|
// testing.expectEqual('p', parentCalls[0].newValue);
|
||||||
testing.expectEqual(0, childCalls.length);
|
// testing.expectEqual(0, childCalls.length);
|
||||||
|
|
||||||
customElements.define('nested-child', NestedChild);
|
// customElements.define('nested-child', NestedChild);
|
||||||
|
|
||||||
testing.expectEqual(1, parentCalls.length);
|
// testing.expectEqual(1, parentCalls.length);
|
||||||
testing.expectEqual(1, childCalls.length);
|
// testing.expectEqual(1, childCalls.length);
|
||||||
testing.expectEqual('child-attr', childCalls[0].name);
|
// testing.expectEqual('child-attr', childCalls[0].name);
|
||||||
testing.expectEqual('c', childCalls[0].newValue);
|
// testing.expectEqual('c', childCalls[0].newValue);
|
||||||
}
|
// }
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -770,8 +770,8 @@ pub fn getAdoptedStyleSheets(self: *Document, page: *Page) !js.Object {
|
|||||||
if (self._adopted_style_sheets) |ass| {
|
if (self._adopted_style_sheets) |ass| {
|
||||||
return ass;
|
return ass;
|
||||||
}
|
}
|
||||||
const js_arr = page.js.createArray(0);
|
const js_arr = page.js.newArray(0);
|
||||||
const js_obj = js_arr.asObject();
|
const js_obj = js_arr.toObject();
|
||||||
self._adopted_style_sheets = try js_obj.persist();
|
self._adopted_style_sheets = try js_obj.persist();
|
||||||
return self._adopted_style_sheets.?;
|
return self._adopted_style_sheets.?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub fn getLength(_: *const History, page: *Page) u32 {
|
|||||||
|
|
||||||
pub fn getState(_: *const History, page: *Page) !?js.Value {
|
pub fn getState(_: *const History, page: *Page) !?js.Value {
|
||||||
if (page._session.navigation.getCurrentEntry()._state.value) |state| {
|
if (page._session.navigation.getCurrentEntry()._state.value) |state| {
|
||||||
const value = try js.Value.fromJson(page.js, state);
|
const value = try page.js.parseJSON(state);
|
||||||
return value;
|
return value;
|
||||||
} else return null;
|
} else return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ pub fn asNode(self: *Custom) *Node {
|
|||||||
|
|
||||||
pub fn invokeConnectedCallback(self: *Custom, page: *Page) void {
|
pub fn invokeConnectedCallback(self: *Custom, page: *Page) void {
|
||||||
// Only invoke if we haven't already called it while connected
|
// Only invoke if we haven't already called it while connected
|
||||||
if (self._connected_callback_invoked) return;
|
if (self._connected_callback_invoked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self._connected_callback_invoked = true;
|
self._connected_callback_invoked = true;
|
||||||
self._disconnected_callback_invoked = false;
|
self._disconnected_callback_invoked = false;
|
||||||
@@ -158,11 +160,11 @@ pub fn invokeAttributeChangedCallbackOnElement(element: *Element, name: []const
|
|||||||
fn invokeCallbackOnElement(element: *Element, definition: *CustomElementDefinition, comptime callback_name: [:0]const u8, args: anytype, page: *Page) void {
|
fn invokeCallbackOnElement(element: *Element, definition: *CustomElementDefinition, comptime callback_name: [:0]const u8, args: anytype, page: *Page) void {
|
||||||
_ = definition;
|
_ = definition;
|
||||||
|
|
||||||
const context = page.js;
|
const ctx = page.js;
|
||||||
|
|
||||||
// Get the JS element object
|
// Get the JS element object
|
||||||
const js_val = context.zigValueToJs(element, .{}) catch return;
|
const js_val = ctx.zigValueToJs(element, .{}) catch return;
|
||||||
const js_element = context.createObject(js_val);
|
const js_element = js_val.toObject();
|
||||||
|
|
||||||
// Call the callback method if it exists
|
// Call the callback method if it exists
|
||||||
js_element.callMethod(void, callback_name, args) catch return;
|
js_element.callMethod(void, callback_name, args) catch return;
|
||||||
@@ -205,10 +207,10 @@ fn invokeCallback(self: *Custom, comptime callback_name: [:0]const u8, args: any
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = page.js;
|
const ctx = page.js;
|
||||||
|
|
||||||
const js_val = context.zigValueToJs(self, .{}) catch return;
|
const js_val = ctx.zigValueToJs(self, .{}) catch return;
|
||||||
const js_element = context.createObject(js_val);
|
const js_element = js_val.toObject();
|
||||||
|
|
||||||
js_element.callMethod(void, callback_name, args) catch return;
|
js_element.callMethod(void, callback_name, args) catch return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,10 +60,8 @@ pub fn asEvent(self: *PopStateEvent) *Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn getState(self: *PopStateEvent, page: *Page) !?js.Value {
|
pub fn getState(self: *PopStateEvent, page: *Page) !?js.Value {
|
||||||
if (self._state == null) return null;
|
const s = self._state orelse return null;
|
||||||
|
return try page.js.parseJSON(s);
|
||||||
const value = try js.Value.fromJson(page.js, self._state.?);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hasUAVisualTransition(_: *PopStateEvent) bool {
|
pub fn hasUAVisualTransition(_: *PopStateEvent) bool {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ pub const StateReturn = union(enum) { value: ?js.Value, undefined: void };
|
|||||||
pub fn getState(self: *const NavigationHistoryEntry, page: *Page) !StateReturn {
|
pub fn getState(self: *const NavigationHistoryEntry, page: *Page) !StateReturn {
|
||||||
if (self._state.source == .navigation) {
|
if (self._state.source == .navigation) {
|
||||||
if (self._state.value) |value| {
|
if (self._state.value) |value| {
|
||||||
return .{ .value = try js.Value.fromJson(page.js, value) };
|
return .{ .value = try page.js.parseJSON(value) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,11 +120,10 @@ pub fn getText(self: *const Response, page: *Page) !js.Promise {
|
|||||||
|
|
||||||
pub fn getJson(self: *Response, page: *Page) !js.Promise {
|
pub fn getJson(self: *Response, page: *Page) !js.Promise {
|
||||||
const body = self._body orelse "";
|
const body = self._body orelse "";
|
||||||
const value = js.Value.fromJson(page.js, body) catch |err| {
|
const value = page.js.parseJSON(body) catch |err| {
|
||||||
return page.js.rejectPromise(.{@errorName(err)});
|
return page.js.rejectPromise(.{@errorName(err)});
|
||||||
};
|
};
|
||||||
const pvalue = try value.persist();
|
return page.js.resolvePromise(try value.persist());
|
||||||
return page.js.resolvePromise(pvalue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const JsApi = struct {
|
pub const JsApi = struct {
|
||||||
|
|||||||
@@ -254,9 +254,8 @@ pub fn getResponse(self: *XMLHttpRequest, page: *Page) !?Response {
|
|||||||
const res: Response = switch (self._response_type) {
|
const res: Response = switch (self._response_type) {
|
||||||
.text => .{ .text = data },
|
.text => .{ .text = data },
|
||||||
.json => blk: {
|
.json => blk: {
|
||||||
const value = try js.Value.fromJson(page.js, data);
|
const value = try page.js.parseJSON(data);
|
||||||
const pvalue = try value.persist();
|
break :blk .{ .json = try value.persist() };
|
||||||
break :blk .{ .json = pvalue };
|
|
||||||
},
|
},
|
||||||
.document => blk: {
|
.document => blk: {
|
||||||
const document = try page._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
|
const document = try page._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
|
||||||
|
|||||||
Reference in New Issue
Block a user