Ability to remove a type from the global's iterable list.

Some types, like AbortController, shouldn't be iterable on the window. This
commit (a) adds the ability to control this in the snapshot, and sets the
iterability based on the dom/interface-objects.html wpt test list.
This commit is contained in:
Karl Seguin
2026-02-11 20:53:13 +08:00
parent 77aa2241dc
commit 151cefe0ec
23 changed files with 28 additions and 6 deletions

View File

@@ -202,12 +202,16 @@ pub fn create() !Snapshot {
const name = JsApi.Meta.name; const name = JsApi.Meta.name;
const illegal_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len)); const illegal_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
var maybe_result2: v8.MaybeBool = undefined; var maybe_result2: v8.MaybeBool = undefined;
v8.v8__Object__Set(global_obj, context, illegal_class_name, func, &maybe_result2); v8.v8__Object__DefineOwnProperty(global_obj, context, illegal_class_name, func, 0, &maybe_result2);
} else { } else {
const name = JsApi.Meta.name; const name = JsApi.Meta.name;
const v8_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len)); const v8_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
var maybe_result: v8.MaybeBool = undefined; var maybe_result: v8.MaybeBool = undefined;
v8.v8__Object__Set(global_obj, context, v8_class_name, func, &maybe_result); var properties: v8.PropertyAttribute = v8.None;
if (@hasDecl(JsApi.Meta, "enumerable") and JsApi.Meta.enumerable == false) {
properties |= v8.DontEnum;
}
v8.v8__Object__DefineOwnProperty(global_obj, context, v8_class_name, func, properties, &maybe_result);
} }
} }
} }

View File

@@ -49,6 +49,7 @@ pub const JsApi = struct {
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(AbortController.init, .{}); pub const constructor = bridge.constructor(AbortController.init, .{});

View File

@@ -157,6 +157,7 @@ pub const JsApi = struct {
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const Prototype = EventTarget; pub const Prototype = EventTarget;

View File

@@ -273,6 +273,7 @@ pub const JsApi = struct {
pub const name = "CharacterData"; pub const name = "CharacterData";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const data = bridge.accessor(CData.getData, CData.setData, .{}); pub const data = bridge.accessor(CData.getData, CData.setData, .{});

View File

@@ -99,6 +99,7 @@ pub const JsApi = struct {
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const empty_with_no_proto = true; pub const empty_with_no_proto = true;
pub const enumerable = false;
}; };
pub const createDocumentType = bridge.function(DOMImplementation.createDocumentType, .{ .dom_exception = true }); pub const createDocumentType = bridge.function(DOMImplementation.createDocumentType, .{ .dom_exception = true });

View File

@@ -192,6 +192,7 @@ pub const JsApi = struct {
pub const name = "NodeIterator"; pub const name = "NodeIterator";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const root = bridge.accessor(DOMNodeIterator.getRoot, null, .{}); pub const root = bridge.accessor(DOMNodeIterator.getRoot, null, .{});

View File

@@ -344,6 +344,7 @@ pub const JsApi = struct {
pub const name = "TreeWalker"; pub const name = "TreeWalker";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const root = bridge.accessor(DOMTreeWalker.getRoot, null, .{}); pub const root = bridge.accessor(DOMTreeWalker.getRoot, null, .{});

View File

@@ -934,6 +934,7 @@ pub const JsApi = struct {
pub const name = "Document"; pub const name = "Document";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(_constructor, .{}); pub const constructor = bridge.constructor(_constructor, .{});

View File

@@ -233,6 +233,7 @@ pub const JsApi = struct {
pub const name = "DocumentFragment"; pub const name = "DocumentFragment";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(DocumentFragment.init, .{}); pub const constructor = bridge.constructor(DocumentFragment.init, .{});

View File

@@ -81,6 +81,7 @@ pub const JsApi = struct {
pub const name = "DocumentType"; pub const name = "DocumentType";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const name = bridge.accessor(DocumentType.getName, null, .{}); pub const name = bridge.accessor(DocumentType.getName, null, .{});

View File

@@ -1425,6 +1425,7 @@ pub const JsApi = struct {
pub const name = "Element"; pub const name = "Element";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const tagName = bridge.accessor(_tagName, null, .{}); pub const tagName = bridge.accessor(_tagName, null, .{});

View File

@@ -409,6 +409,7 @@ pub const JsApi = struct {
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const weak = true; pub const weak = true;
pub const finalizer = bridge.finalizer(Event.deinit); pub const finalizer = bridge.finalizer(Event.deinit);
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(Event.init, .{}); pub const constructor = bridge.constructor(Event.init, .{});

View File

@@ -162,6 +162,7 @@ pub const JsApi = struct {
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(EventTarget.init, .{}); pub const constructor = bridge.constructor(EventTarget.init, .{});

View File

@@ -879,6 +879,7 @@ pub const JsApi = struct {
pub const name = "Node"; pub const name = "Node";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const ELEMENT_NODE = bridge.property(1, .{ .template = true }); pub const ELEMENT_NODE = bridge.property(1, .{ .template = true });

View File

@@ -88,6 +88,7 @@ pub const JsApi = struct {
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const empty_with_no_proto = true; pub const empty_with_no_proto = true;
pub const enumerable = false;
}; };
pub const FILTER_ACCEPT = bridge.property(NodeFilter.FILTER_ACCEPT, .{ .template = true }); pub const FILTER_ACCEPT = bridge.property(NodeFilter.FILTER_ACCEPT, .{ .template = true });

View File

@@ -37,6 +37,7 @@ pub const JsApi = struct {
pub const name = "Comment"; pub const name = "Comment";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(Comment.init, .{}); pub const constructor = bridge.constructor(Comment.init, .{});

View File

@@ -36,6 +36,7 @@ pub const JsApi = struct {
pub const name = "ProcessingInstruction"; pub const name = "ProcessingInstruction";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const target = bridge.accessor(ProcessingInstruction.getTarget, null, .{}); pub const target = bridge.accessor(ProcessingInstruction.getTarget, null, .{});

View File

@@ -69,6 +69,7 @@ pub const JsApi = struct {
pub const name = "Text"; pub const name = "Text";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(Text.init, .{}); pub const constructor = bridge.constructor(Text.init, .{});

View File

@@ -251,6 +251,7 @@ pub const JsApi = struct {
pub const name = "DOMTokenList"; pub const name = "DOMTokenList";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const length = bridge.accessor(DOMTokenList.length, null, .{}); pub const length = bridge.accessor(DOMTokenList.length, null, .{});

View File

@@ -127,6 +127,7 @@ pub const JsApi = struct {
pub const name = "HTMLCollection"; pub const name = "HTMLCollection";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const length = bridge.accessor(HTMLCollection.length, null, .{}); pub const length = bridge.accessor(HTMLCollection.length, null, .{});

View File

@@ -117,6 +117,7 @@ pub const JsApi = struct {
pub const name = "NodeList"; pub const name = "NodeList";
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const length = bridge.accessor(NodeList.length, null, .{}); pub const length = bridge.accessor(NodeList.length, null, .{});

View File

@@ -94,12 +94,9 @@ pub const JsApi = struct {
pub const Meta = struct { pub const Meta = struct {
pub const name = "Attr"; pub const name = "Attr";
// we _never_ hold a reference to this, so the JS layer doesn't need to
// persist the value. It can pass it to QuickJS and let it fully manage it
// (TODO: we probably _should_ hold a refernece, because calling getAttributeNode
// on the same element + name should return the same instance)
pub const prototype_chain = bridge.prototypeChain(); pub const prototype_chain = bridge.prototypeChain();
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
}; };
pub const name = bridge.accessor(Attribute.getName, null, .{}); pub const name = bridge.accessor(Attribute.getName, null, .{});

View File

@@ -97,6 +97,7 @@ pub const JsApi = struct {
pub var class_id: bridge.ClassId = undefined; pub var class_id: bridge.ClassId = undefined;
pub const weak = true; pub const weak = true;
pub const finalizer = bridge.finalizer(CustomEvent.deinit); pub const finalizer = bridge.finalizer(CustomEvent.deinit);
pub const enumerable = false;
}; };
pub const constructor = bridge.constructor(CustomEvent.init, .{}); pub const constructor = bridge.constructor(CustomEvent.init, .{});