mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Adds Document.prerendering
Expands bridge.property to work as a getter. This previously only worked by
setting a value directly on the TemplatePrototype. This is what you want for
something like Node.TEXT_NODE which is accessible on both Node and an instance
(e.g. document.createElement('div').TEXT_NODE).
Now the property can be configured with .{.template = false}. It essentially
becomes an optimized: bridge.accessor(comptime scalar, null, .{});
There are other accessor that can be converted to this type, but I'll do that
after this is merged to keep this PR manageable.
This commit is contained in:
@@ -280,6 +280,7 @@ fn countExternalReferences() comptime_int {
|
||||
|
||||
// +1 for the illegal constructor callback
|
||||
var count: comptime_int = 1;
|
||||
var has_non_template_property: bool = false;
|
||||
|
||||
inline for (JsApis) |JsApi| {
|
||||
// Constructor (only if explicit)
|
||||
@@ -302,6 +303,10 @@ fn countExternalReferences() comptime_int {
|
||||
if (value.setter != null) count += 1; // setter
|
||||
} else if (T == bridge.Function) {
|
||||
count += 1;
|
||||
} else if (T == bridge.Property) {
|
||||
if (value.template == false) {
|
||||
has_non_template_property = true;
|
||||
}
|
||||
} else if (T == bridge.Iterator) {
|
||||
count += 1;
|
||||
} else if (T == bridge.Indexed) {
|
||||
@@ -314,6 +319,10 @@ fn countExternalReferences() comptime_int {
|
||||
}
|
||||
}
|
||||
|
||||
if (has_non_template_property) {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// In debug mode, add unknown property callbacks for types without NamedIndexed
|
||||
if (comptime IS_DEBUG) {
|
||||
inline for (JsApis) |JsApi| {
|
||||
@@ -333,6 +342,8 @@ fn collectExternalReferences() [countExternalReferences()]isize {
|
||||
references[idx] = @bitCast(@intFromPtr(&illegalConstructorCallback));
|
||||
idx += 1;
|
||||
|
||||
var has_non_template_property = false;
|
||||
|
||||
inline for (JsApis) |JsApi| {
|
||||
if (@hasDecl(JsApi, "constructor")) {
|
||||
references[idx] = @bitCast(@intFromPtr(JsApi.constructor.func));
|
||||
@@ -358,6 +369,10 @@ fn collectExternalReferences() [countExternalReferences()]isize {
|
||||
} else if (T == bridge.Function) {
|
||||
references[idx] = @bitCast(@intFromPtr(value.func));
|
||||
idx += 1;
|
||||
} else if (T == bridge.Property) {
|
||||
if (value.template == false) {
|
||||
has_non_template_property = true;
|
||||
}
|
||||
} else if (T == bridge.Iterator) {
|
||||
references[idx] = @bitCast(@intFromPtr(value.func));
|
||||
idx += 1;
|
||||
@@ -379,6 +394,11 @@ fn collectExternalReferences() [countExternalReferences()]isize {
|
||||
}
|
||||
}
|
||||
|
||||
if (has_non_template_property) {
|
||||
references[idx] = @bitCast(@intFromPtr(&bridge.Property.getter));
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
// In debug mode, collect unknown property callbacks for types without NamedIndexed
|
||||
if (comptime IS_DEBUG) {
|
||||
inline for (JsApis) |JsApi| {
|
||||
@@ -497,17 +517,24 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
|
||||
v8.v8__Template__Set(@ptrCast(target), js_name, @ptrCast(function_template), v8.None);
|
||||
},
|
||||
bridge.Property => {
|
||||
// simpleZigValueToJs now returns raw handle directly
|
||||
const js_value = switch (value) {
|
||||
.int => |v| js.simpleZigValueToJs(.{ .handle = isolate }, v, true, false),
|
||||
const js_value = switch (value.value) {
|
||||
inline .bool, .int => |v| js.simpleZigValueToJs(.{ .handle = isolate }, v, true, false),
|
||||
};
|
||||
|
||||
const js_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
|
||||
// apply it both to the type itself
|
||||
v8.v8__Template__Set(@ptrCast(template), js_name, js_value, v8.ReadOnly + v8.DontDelete);
|
||||
|
||||
// and to instances of the type
|
||||
v8.v8__Template__Set(@ptrCast(target), js_name, js_value, v8.ReadOnly + v8.DontDelete);
|
||||
if (value.template == false) {
|
||||
// not defined on the template, only on the instance. This
|
||||
// is like an Accessor, but because the value is known at
|
||||
// compile time, we skip _a lot_ of code and quickly return
|
||||
// the hard-coded value
|
||||
const getter_callback = @constCast(v8.v8__FunctionTemplate__New__DEFAULT3(isolate, bridge.Property.getter, js_value));
|
||||
v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT(target, js_name, getter_callback);
|
||||
} else {
|
||||
// apply it both to the type itself
|
||||
v8.v8__Template__Set(@ptrCast(template), js_name, js_value, v8.ReadOnly + v8.DontDelete);
|
||||
// and to instances of the type
|
||||
v8.v8__Template__Set(@ptrCast(target), js_name, js_value, v8.ReadOnly + v8.DontDelete);
|
||||
}
|
||||
},
|
||||
bridge.Constructor => {}, // already handled in generateConstructor
|
||||
else => {},
|
||||
|
||||
@@ -62,12 +62,13 @@ pub fn Builder(comptime T: type) type {
|
||||
return Callable.init(T, func, opts);
|
||||
}
|
||||
|
||||
pub fn property(value: anytype) Property {
|
||||
switch (@typeInfo(@TypeOf(value))) {
|
||||
.comptime_int, .int => return .{ .int = value },
|
||||
else => {},
|
||||
}
|
||||
@compileError("Property for " ++ @typeName(@TypeOf(value)) ++ " hasn't been defined yet");
|
||||
pub fn property(value: anytype, opts: Property.Opts) Property {
|
||||
// If you add strings to this, they might need to be internalized!
|
||||
return switch (@typeInfo(@TypeOf(value))) {
|
||||
.bool => Property.init(.{ .bool = value }, opts),
|
||||
.comptime_int, .int => Property.init(.{ .int = value }, opts),
|
||||
else => @compileError("Property for " ++ @typeName(@TypeOf(value)) ++ " hasn't been defined yet"),
|
||||
};
|
||||
}
|
||||
|
||||
const PrototypeChainEntry = @import("TaggedOpaque.zig").PrototypeChainEntry;
|
||||
@@ -398,8 +399,33 @@ pub const Callable = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Property = union(enum) {
|
||||
int: i64,
|
||||
pub const Property = struct {
|
||||
value: Value,
|
||||
template: bool,
|
||||
|
||||
// If you add strings to this, they might need to be internalized!
|
||||
const Value = union(enum) {
|
||||
int: i64,
|
||||
bool: bool,
|
||||
};
|
||||
|
||||
const Opts = struct {
|
||||
template: bool,
|
||||
};
|
||||
|
||||
fn init(value: Value, opts: Opts) Property {
|
||||
return .{
|
||||
.value = value,
|
||||
.template = opts.template,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getter(handle: ?*const v8.FunctionCallbackInfo) callconv(.c) void {
|
||||
const value = v8.v8__FunctionCallbackInfo__Data(handle.?);
|
||||
var rv: v8.ReturnValue = undefined;
|
||||
v8.v8__FunctionCallbackInfo__GetReturnValue(handle.?, &rv);
|
||||
v8.v8__ReturnValue__Set(rv, value);
|
||||
}
|
||||
};
|
||||
|
||||
const Finalizer = struct {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
testing.expectEqual(window, document.defaultView);
|
||||
testing.expectEqual(false, document.hidden);
|
||||
testing.expectEqual("visible", document.visibilityState);
|
||||
testing.expectEqual(false, document.prerendering);
|
||||
testing.expectEqual(undefined, Document.prerendering);
|
||||
</script>
|
||||
|
||||
<script id=headAndbody>
|
||||
|
||||
@@ -1004,6 +1004,7 @@ pub const JsApi = struct {
|
||||
pub const adoptedStyleSheets = bridge.accessor(Document.getAdoptedStyleSheets, Document.setAdoptedStyleSheets, .{});
|
||||
pub const hidden = bridge.accessor(Document.getHidden, null, .{});
|
||||
pub const visibilityState = bridge.accessor(Document.getVisibilityState, null, .{});
|
||||
pub const prerendering = bridge.property(false, .{ .template = false });
|
||||
|
||||
pub const defaultView = bridge.accessor(struct {
|
||||
fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") {
|
||||
|
||||
@@ -410,10 +410,10 @@ pub const JsApi = struct {
|
||||
pub const cancelBubble = bridge.accessor(Event.getCancelBubble, Event.setCancelBubble, .{});
|
||||
|
||||
// Event phase constants
|
||||
pub const NONE = bridge.property(@intFromEnum(EventPhase.none));
|
||||
pub const CAPTURING_PHASE = bridge.property(@intFromEnum(EventPhase.capturing_phase));
|
||||
pub const AT_TARGET = bridge.property(@intFromEnum(EventPhase.at_target));
|
||||
pub const BUBBLING_PHASE = bridge.property(@intFromEnum(EventPhase.bubbling_phase));
|
||||
pub const NONE = bridge.property(@intFromEnum(EventPhase.none), .{ .template = true });
|
||||
pub const CAPTURING_PHASE = bridge.property(@intFromEnum(EventPhase.capturing_phase), .{ .template = true });
|
||||
pub const AT_TARGET = bridge.property(@intFromEnum(EventPhase.at_target), .{ .template = true });
|
||||
pub const BUBBLING_PHASE = bridge.property(@intFromEnum(EventPhase.bubbling_phase), .{ .template = true });
|
||||
};
|
||||
|
||||
// tested in event_target
|
||||
|
||||
@@ -874,25 +874,25 @@ pub const JsApi = struct {
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const ELEMENT_NODE = bridge.property(1);
|
||||
pub const ATTRIBUTE_NODE = bridge.property(2);
|
||||
pub const TEXT_NODE = bridge.property(3);
|
||||
pub const CDATA_SECTION_NODE = bridge.property(4);
|
||||
pub const ENTITY_REFERENCE_NODE = bridge.property(5);
|
||||
pub const ENTITY_NODE = bridge.property(6);
|
||||
pub const PROCESSING_INSTRUCTION_NODE = bridge.property(7);
|
||||
pub const COMMENT_NODE = bridge.property(8);
|
||||
pub const DOCUMENT_NODE = bridge.property(9);
|
||||
pub const DOCUMENT_TYPE_NODE = bridge.property(10);
|
||||
pub const DOCUMENT_FRAGMENT_NODE = bridge.property(11);
|
||||
pub const NOTATION_NODE = bridge.property(12);
|
||||
pub const ELEMENT_NODE = bridge.property(1, .{ .template = true });
|
||||
pub const ATTRIBUTE_NODE = bridge.property(2, .{ .template = true });
|
||||
pub const TEXT_NODE = bridge.property(3, .{ .template = true });
|
||||
pub const CDATA_SECTION_NODE = bridge.property(4, .{ .template = true });
|
||||
pub const ENTITY_REFERENCE_NODE = bridge.property(5, .{ .template = true });
|
||||
pub const ENTITY_NODE = bridge.property(6, .{ .template = true });
|
||||
pub const PROCESSING_INSTRUCTION_NODE = bridge.property(7, .{ .template = true });
|
||||
pub const COMMENT_NODE = bridge.property(8, .{ .template = true });
|
||||
pub const DOCUMENT_NODE = bridge.property(9, .{ .template = true });
|
||||
pub const DOCUMENT_TYPE_NODE = bridge.property(10, .{ .template = true });
|
||||
pub const DOCUMENT_FRAGMENT_NODE = bridge.property(11, .{ .template = true });
|
||||
pub const NOTATION_NODE = bridge.property(12, .{ .template = true });
|
||||
|
||||
pub const DOCUMENT_POSITION_DISCONNECTED = bridge.property(0x01);
|
||||
pub const DOCUMENT_POSITION_PRECEDING = bridge.property(0x02);
|
||||
pub const DOCUMENT_POSITION_FOLLOWING = bridge.property(0x04);
|
||||
pub const DOCUMENT_POSITION_CONTAINS = bridge.property(0x08);
|
||||
pub const DOCUMENT_POSITION_CONTAINED_BY = bridge.property(0x10);
|
||||
pub const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = bridge.property(0x20);
|
||||
pub const DOCUMENT_POSITION_DISCONNECTED = bridge.property(0x01, .{ .template = true });
|
||||
pub const DOCUMENT_POSITION_PRECEDING = bridge.property(0x02, .{ .template = true });
|
||||
pub const DOCUMENT_POSITION_FOLLOWING = bridge.property(0x04, .{ .template = true });
|
||||
pub const DOCUMENT_POSITION_CONTAINS = bridge.property(0x08, .{ .template = true });
|
||||
pub const DOCUMENT_POSITION_CONTAINED_BY = bridge.property(0x10, .{ .template = true });
|
||||
pub const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = bridge.property(0x20, .{ .template = true });
|
||||
|
||||
pub const nodeName = bridge.accessor(struct {
|
||||
fn wrap(self: *const Node, page: *Page) []const u8 {
|
||||
|
||||
@@ -90,21 +90,21 @@ pub const JsApi = struct {
|
||||
pub const empty_with_no_proto = true;
|
||||
};
|
||||
|
||||
pub const FILTER_ACCEPT = bridge.property(NodeFilter.FILTER_ACCEPT);
|
||||
pub const FILTER_REJECT = bridge.property(NodeFilter.FILTER_REJECT);
|
||||
pub const FILTER_SKIP = bridge.property(NodeFilter.FILTER_SKIP);
|
||||
pub const FILTER_ACCEPT = bridge.property(NodeFilter.FILTER_ACCEPT, .{ .template = true });
|
||||
pub const FILTER_REJECT = bridge.property(NodeFilter.FILTER_REJECT, .{ .template = true });
|
||||
pub const FILTER_SKIP = bridge.property(NodeFilter.FILTER_SKIP, .{ .template = true });
|
||||
|
||||
pub const SHOW_ALL = bridge.property(NodeFilter.SHOW_ALL);
|
||||
pub const SHOW_ELEMENT = bridge.property(NodeFilter.SHOW_ELEMENT);
|
||||
pub const SHOW_ATTRIBUTE = bridge.property(NodeFilter.SHOW_ATTRIBUTE);
|
||||
pub const SHOW_TEXT = bridge.property(NodeFilter.SHOW_TEXT);
|
||||
pub const SHOW_CDATA_SECTION = bridge.property(NodeFilter.SHOW_CDATA_SECTION);
|
||||
pub const SHOW_ENTITY_REFERENCE = bridge.property(NodeFilter.SHOW_ENTITY_REFERENCE);
|
||||
pub const SHOW_ENTITY = bridge.property(NodeFilter.SHOW_ENTITY);
|
||||
pub const SHOW_PROCESSING_INSTRUCTION = bridge.property(NodeFilter.SHOW_PROCESSING_INSTRUCTION);
|
||||
pub const SHOW_COMMENT = bridge.property(NodeFilter.SHOW_COMMENT);
|
||||
pub const SHOW_DOCUMENT = bridge.property(NodeFilter.SHOW_DOCUMENT);
|
||||
pub const SHOW_DOCUMENT_TYPE = bridge.property(NodeFilter.SHOW_DOCUMENT_TYPE);
|
||||
pub const SHOW_DOCUMENT_FRAGMENT = bridge.property(NodeFilter.SHOW_DOCUMENT_FRAGMENT);
|
||||
pub const SHOW_NOTATION = bridge.property(NodeFilter.SHOW_NOTATION);
|
||||
pub const SHOW_ALL = bridge.property(NodeFilter.SHOW_ALL, .{ .template = true });
|
||||
pub const SHOW_ELEMENT = bridge.property(NodeFilter.SHOW_ELEMENT, .{ .template = true });
|
||||
pub const SHOW_ATTRIBUTE = bridge.property(NodeFilter.SHOW_ATTRIBUTE, .{ .template = true });
|
||||
pub const SHOW_TEXT = bridge.property(NodeFilter.SHOW_TEXT, .{ .template = true });
|
||||
pub const SHOW_CDATA_SECTION = bridge.property(NodeFilter.SHOW_CDATA_SECTION, .{ .template = true });
|
||||
pub const SHOW_ENTITY_REFERENCE = bridge.property(NodeFilter.SHOW_ENTITY_REFERENCE, .{ .template = true });
|
||||
pub const SHOW_ENTITY = bridge.property(NodeFilter.SHOW_ENTITY, .{ .template = true });
|
||||
pub const SHOW_PROCESSING_INSTRUCTION = bridge.property(NodeFilter.SHOW_PROCESSING_INSTRUCTION, .{ .template = true });
|
||||
pub const SHOW_COMMENT = bridge.property(NodeFilter.SHOW_COMMENT, .{ .template = true });
|
||||
pub const SHOW_DOCUMENT = bridge.property(NodeFilter.SHOW_DOCUMENT, .{ .template = true });
|
||||
pub const SHOW_DOCUMENT_TYPE = bridge.property(NodeFilter.SHOW_DOCUMENT_TYPE, .{ .template = true });
|
||||
pub const SHOW_DOCUMENT_FRAGMENT = bridge.property(NodeFilter.SHOW_DOCUMENT_FRAGMENT, .{ .template = true });
|
||||
pub const SHOW_NOTATION = bridge.property(NodeFilter.SHOW_NOTATION, .{ .template = true });
|
||||
};
|
||||
|
||||
@@ -565,10 +565,10 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
// Constants for compareBoundaryPoints
|
||||
pub const START_TO_START = bridge.property(0);
|
||||
pub const START_TO_END = bridge.property(1);
|
||||
pub const END_TO_END = bridge.property(2);
|
||||
pub const END_TO_START = bridge.property(3);
|
||||
pub const START_TO_START = bridge.property(0, .{ .template = true });
|
||||
pub const START_TO_END = bridge.property(1, .{ .template = true });
|
||||
pub const END_TO_END = bridge.property(2, .{ .template = true });
|
||||
pub const END_TO_START = bridge.property(3, .{ .template = true });
|
||||
|
||||
pub const constructor = bridge.constructor(Range.init, .{});
|
||||
pub const setStart = bridge.function(Range.setStart, .{ .dom_exception = true });
|
||||
|
||||
@@ -284,16 +284,16 @@ pub const JsApi = struct {
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const NETWORK_EMPTY = bridge.property(@intFromEnum(NetworkState.NETWORK_EMPTY));
|
||||
pub const NETWORK_IDLE = bridge.property(@intFromEnum(NetworkState.NETWORK_IDLE));
|
||||
pub const NETWORK_LOADING = bridge.property(@intFromEnum(NetworkState.NETWORK_LOADING));
|
||||
pub const NETWORK_NO_SOURCE = bridge.property(@intFromEnum(NetworkState.NETWORK_NO_SOURCE));
|
||||
pub const NETWORK_EMPTY = bridge.property(@intFromEnum(NetworkState.NETWORK_EMPTY), .{ .template = true });
|
||||
pub const NETWORK_IDLE = bridge.property(@intFromEnum(NetworkState.NETWORK_IDLE), .{ .template = true });
|
||||
pub const NETWORK_LOADING = bridge.property(@intFromEnum(NetworkState.NETWORK_LOADING), .{ .template = true });
|
||||
pub const NETWORK_NO_SOURCE = bridge.property(@intFromEnum(NetworkState.NETWORK_NO_SOURCE), .{ .template = true });
|
||||
|
||||
pub const HAVE_NOTHING = bridge.property(@intFromEnum(ReadyState.HAVE_NOTHING));
|
||||
pub const HAVE_METADATA = bridge.property(@intFromEnum(ReadyState.HAVE_METADATA));
|
||||
pub const HAVE_CURRENT_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_CURRENT_DATA));
|
||||
pub const HAVE_FUTURE_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_FUTURE_DATA));
|
||||
pub const HAVE_ENOUGH_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_ENOUGH_DATA));
|
||||
pub const HAVE_NOTHING = bridge.property(@intFromEnum(ReadyState.HAVE_NOTHING), .{ .template = true });
|
||||
pub const HAVE_METADATA = bridge.property(@intFromEnum(ReadyState.HAVE_METADATA), .{ .template = true });
|
||||
pub const HAVE_CURRENT_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_CURRENT_DATA), .{ .template = true });
|
||||
pub const HAVE_FUTURE_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_FUTURE_DATA), .{ .template = true });
|
||||
pub const HAVE_ENOUGH_DATA = bridge.property(@intFromEnum(ReadyState.HAVE_ENOUGH_DATA), .{ .template = true });
|
||||
|
||||
pub const src = bridge.accessor(Media.getSrc, Media.setSrc, .{});
|
||||
pub const autoplay = bridge.accessor(Media.getAutoplay, Media.setAutoplay, .{});
|
||||
|
||||
@@ -49,10 +49,10 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
// Error code constants
|
||||
pub const MEDIA_ERR_ABORTED = bridge.property(1);
|
||||
pub const MEDIA_ERR_NETWORK = bridge.property(2);
|
||||
pub const MEDIA_ERR_DECODE = bridge.property(3);
|
||||
pub const MEDIA_ERR_SRC_NOT_SUPPORTED = bridge.property(4);
|
||||
pub const MEDIA_ERR_ABORTED = bridge.property(1, .{ .template = true });
|
||||
pub const MEDIA_ERR_NETWORK = bridge.property(2, .{ .template = true });
|
||||
pub const MEDIA_ERR_DECODE = bridge.property(3, .{ .template = true });
|
||||
pub const MEDIA_ERR_SRC_NOT_SUPPORTED = bridge.property(4, .{ .template = true });
|
||||
|
||||
pub const code = bridge.accessor(MediaError.getCode, null, .{});
|
||||
pub const message = bridge.accessor(MediaError.getMessage, null, .{});
|
||||
|
||||
@@ -552,11 +552,11 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(XMLHttpRequest.init, .{});
|
||||
pub const UNSENT = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.unsent));
|
||||
pub const OPENED = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.opened));
|
||||
pub const HEADERS_RECEIVED = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.headers_received));
|
||||
pub const LOADING = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.loading));
|
||||
pub const DONE = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.done));
|
||||
pub const UNSENT = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.unsent), .{ .template = true });
|
||||
pub const OPENED = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.opened), .{ .template = true });
|
||||
pub const HEADERS_RECEIVED = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.headers_received), .{ .template = true });
|
||||
pub const LOADING = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.loading), .{ .template = true });
|
||||
pub const DONE = bridge.property(@intFromEnum(XMLHttpRequest.ReadyState.done), .{ .template = true });
|
||||
|
||||
pub const onreadystatechange = bridge.accessor(XMLHttpRequest.getOnReadyStateChange, XMLHttpRequest.setOnReadyStateChange, .{});
|
||||
pub const withCredentials = bridge.accessor(XMLHttpRequest.getWithCredentials, XMLHttpRequest.setWithCredentials, .{ .dom_exception = true });
|
||||
|
||||
Reference in New Issue
Block a user