mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-31 17:55:59 -04:00
webapi: Make all interfaces non-enumerable
When I added this, I was going through the list in /dom/interface-objects.html thinking that was exhaustive. But no, no interfaces should be enumerable and various other WPT tests (usually the idlharness ones) assert that for their respective types. Make it _always_ non enumerable means we no longer need Meta.enumerable to be declared true/false (it's always false).
This commit is contained in:
@@ -314,13 +314,8 @@ fn createSnapshotContext(
|
||||
const name = JsApi.Meta.name;
|
||||
const v8_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
|
||||
var maybe_result: v8.MaybeBool = undefined;
|
||||
// Web IDL: interface objects on the global are non-enumerable
|
||||
// by default. Opt back in via JsApi.Meta.enumerable = true.
|
||||
var properties: v8.PropertyAttribute = v8.DontEnum;
|
||||
if (@hasDecl(JsApi.Meta, "enumerable") and JsApi.Meta.enumerable == true) {
|
||||
properties = v8.None;
|
||||
}
|
||||
v8.v8__Object__DefineOwnProperty(global_obj, context, v8_class_name, func, properties, &maybe_result);
|
||||
// Web IDL: interface objects on the global are non-enumerable.
|
||||
v8.v8__Object__DefineOwnProperty(global_obj, context, v8_class_name, func, v8.DontEnum, &maybe_result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,12 +754,13 @@ fn attachClass(comptime JsApi: type, comptime flatten: bool, isolate: *v8.Isolat
|
||||
if (value.static) {
|
||||
v8.v8__Template__SetAccessorProperty(@ptrCast(template), js_name, getter_callback, setter_callback, attribute);
|
||||
} else {
|
||||
const accessor_attr = if (own_properties) attribute else attribute | v8.DontEnum;
|
||||
// Web IDL: attributes on the interface prototype object
|
||||
// (and mirrored onto [Global] instances) are enumerable.
|
||||
v8.v8__ObjectTemplate__SetAccessorProperty__Config(define_on orelse prototype, &.{
|
||||
.key = js_name,
|
||||
.getter = getter_callback,
|
||||
.setter = setter_callback,
|
||||
.attribute = accessor_attr,
|
||||
.attribute = attribute,
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -785,8 +781,9 @@ fn attachClass(comptime JsApi: type, comptime flatten: bool, isolate: *v8.Isolat
|
||||
if (value.static and !own_properties) {
|
||||
v8.v8__Template__Set(@ptrCast(template), js_name, @ptrCast(function_template), v8.None);
|
||||
} else {
|
||||
const fn_attr: v8.PropertyAttribute = if (own_properties) v8.None else v8.DontEnum;
|
||||
v8.v8__Template__Set(@ptrCast(define_on orelse member_template), js_name, @ptrCast(function_template), fn_attr);
|
||||
// Web IDL: operations on the interface prototype object
|
||||
// (and mirrored onto [Global] instances) are enumerable.
|
||||
v8.v8__Template__Set(@ptrCast(define_on orelse member_template), js_name, @ptrCast(function_template), v8.None);
|
||||
}
|
||||
},
|
||||
bridge.Indexed => {
|
||||
@@ -825,7 +822,8 @@ fn attachClass(comptime JsApi: type, comptime flatten: bool, isolate: *v8.Isolat
|
||||
v8.v8__Symbol__GetAsyncIterator(isolate)
|
||||
else
|
||||
v8.v8__Symbol__GetIterator(isolate);
|
||||
v8.v8__Template__Set(@ptrCast(prototype), js_name, @ptrCast(function_template), v8.None);
|
||||
// Web IDL: @@iterator is { writable, enumerable: false, configurable }.
|
||||
v8.v8__Template__Set(@ptrCast(prototype), js_name, @ptrCast(function_template), v8.DontEnum);
|
||||
},
|
||||
bridge.Property => {
|
||||
const js_value = switch (value.value) {
|
||||
|
||||
@@ -489,23 +489,30 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=prototypeMembersAreNonEnumerable>
|
||||
<script id=prototypeMembersAreEnumerable>
|
||||
{
|
||||
// Per WebIDL, interface prototype members are non-enumerable. Several
|
||||
// libraries iterate caller-supplied objects with `for..in` or
|
||||
// `Object.keys` to build querystrings; if prototype methods leak in,
|
||||
// they end up serialized as URL params with values like
|
||||
// "function has() { [native code] }". Real Chrome/Firefox return [].
|
||||
testing.expectEqual([], Object.keys(URLSearchParams.prototype));
|
||||
// Per WebIDL, operations and attributes on an interface prototype object
|
||||
// are enumerable (unlike ES class methods). Real Chrome/Firefox list them
|
||||
// in Object.keys(URLSearchParams.prototype) and in for..in over instances.
|
||||
const proto_keys = Object.keys(URLSearchParams.prototype);
|
||||
testing.expectEqual(true, proto_keys.includes('append'));
|
||||
testing.expectEqual(true, proto_keys.includes('has'));
|
||||
testing.expectEqual(true, proto_keys.includes('size'));
|
||||
|
||||
const usp = new URLSearchParams('a=1&b=2');
|
||||
const keys = [];
|
||||
for (const k in usp) keys.push(k);
|
||||
testing.expectEqual([], keys);
|
||||
testing.expectEqual(true, keys.includes('get'));
|
||||
|
||||
// Sanity: instance own enumerable keys are still empty (entries live in
|
||||
// the C++ side, exposed only via the iterator protocol).
|
||||
// Instance own enumerable keys are still empty (entries live in the
|
||||
// native side, exposed only via the iterator protocol).
|
||||
testing.expectEqual([], Object.keys(usp));
|
||||
|
||||
// But @@iterator and the interface object itself are non-enumerable.
|
||||
const it_desc = Object.getOwnPropertyDescriptor(URLSearchParams.prototype, Symbol.iterator);
|
||||
testing.expectEqual(false, it_desc.enumerable);
|
||||
const iface_desc = Object.getOwnPropertyDescriptor(window, 'URLSearchParams');
|
||||
testing.expectEqual(false, iface_desc.enumerable);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ pub const JsApi = struct {
|
||||
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(AbortController.init, .{});
|
||||
|
||||
@@ -233,7 +233,6 @@ pub const JsApi = struct {
|
||||
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const Prototype = EventTarget;
|
||||
|
||||
@@ -420,7 +420,6 @@ pub const JsApi = struct {
|
||||
pub const name = "CharacterData";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const data = bridge.accessor(CData.getData, CData._setData, .{ .ce_reactions = true });
|
||||
|
||||
@@ -99,7 +99,6 @@ pub const JsApi = struct {
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const empty_with_no_proto = true;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const createDocumentType = bridge.function(DOMImplementation.createDocumentType, .{ .dom_exception = true });
|
||||
|
||||
@@ -191,7 +191,6 @@ pub const JsApi = struct {
|
||||
pub const name = "NodeIterator";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const root = bridge.accessor(DOMNodeIterator.getRoot, null, .{});
|
||||
|
||||
@@ -343,7 +343,6 @@ pub const JsApi = struct {
|
||||
pub const name = "TreeWalker";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const root = bridge.accessor(DOMTreeWalker.getRoot, null, .{});
|
||||
|
||||
@@ -1254,7 +1254,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Document";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(_constructor, .{});
|
||||
|
||||
@@ -192,7 +192,6 @@ pub const JsApi = struct {
|
||||
pub const name = "DocumentFragment";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(DocumentFragment.init, .{});
|
||||
|
||||
@@ -87,7 +87,6 @@ pub const JsApi = struct {
|
||||
pub const name = "DocumentType";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const name = bridge.accessor(DocumentType.getName, null, .{});
|
||||
|
||||
@@ -1913,7 +1913,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Element";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const tagName = bridge.accessor(_tagName, null, .{});
|
||||
|
||||
@@ -465,7 +465,6 @@ pub const JsApi = struct {
|
||||
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(Event.init, .{});
|
||||
|
||||
@@ -201,7 +201,6 @@ pub const JsApi = struct {
|
||||
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(EventTarget.init, .{});
|
||||
|
||||
@@ -1276,7 +1276,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Node";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const ELEMENT_NODE = bridge.property(1, .{ .template = true });
|
||||
|
||||
@@ -87,7 +87,6 @@ pub const JsApi = struct {
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const empty_with_no_proto = true;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const FILTER_ACCEPT = bridge.property(NodeFilter.FILTER_ACCEPT, .{ .template = true });
|
||||
|
||||
@@ -37,7 +37,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Comment";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(Comment.init, .{});
|
||||
|
||||
@@ -36,7 +36,6 @@ pub const JsApi = struct {
|
||||
pub const name = "ProcessingInstruction";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const target = bridge.accessor(ProcessingInstruction.getTarget, null, .{});
|
||||
|
||||
@@ -78,7 +78,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Text";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(Text.init, .{});
|
||||
|
||||
@@ -298,7 +298,6 @@ pub const JsApi = struct {
|
||||
pub const name = "DOMTokenList";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(DOMTokenList.length, null, .{});
|
||||
|
||||
@@ -143,7 +143,6 @@ pub const JsApi = struct {
|
||||
pub const name = "HTMLCollection";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(HTMLCollection.length, null, .{});
|
||||
|
||||
@@ -142,7 +142,6 @@ pub const JsApi = struct {
|
||||
pub const name = "NodeList";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(NodeList.length, null, .{});
|
||||
|
||||
@@ -99,7 +99,6 @@ pub const JsApi = struct {
|
||||
pub const name = "Attr";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const name = bridge.accessor(Attribute.getName, null, .{});
|
||||
|
||||
@@ -105,7 +105,6 @@ pub const JsApi = struct {
|
||||
pub const name = "CustomEvent";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const enumerable = false;
|
||||
};
|
||||
|
||||
pub const constructor = bridge.constructor(CustomEvent.init, .{});
|
||||
|
||||
Reference in New Issue
Block a user