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 illegal_class_name = v8.v8__String__NewFromUtf8(isolate, name.ptr, v8.kNormal, @intCast(name.len));
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 {
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;
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 var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
};
pub const constructor = bridge.constructor(AbortController.init, .{});

View File

@@ -157,6 +157,7 @@ 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;

View File

@@ -273,6 +273,7 @@ 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, .{});

View File

@@ -99,6 +99,7 @@ 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 });

View File

@@ -192,6 +192,7 @@ 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, .{});

View File

@@ -344,6 +344,7 @@ 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, .{});

View File

@@ -934,6 +934,7 @@ 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, .{});

View File

@@ -233,6 +233,7 @@ 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, .{});

View File

@@ -81,6 +81,7 @@ 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, .{});

View File

@@ -1425,6 +1425,7 @@ 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, .{});

View File

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

View File

@@ -162,6 +162,7 @@ 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, .{});

View File

@@ -879,6 +879,7 @@ 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 });

View File

@@ -88,6 +88,7 @@ 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 });

View File

@@ -37,6 +37,7 @@ 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, .{});

View File

@@ -36,6 +36,7 @@ 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, .{});

View File

@@ -69,6 +69,7 @@ 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, .{});

View File

@@ -251,6 +251,7 @@ 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, .{});

View File

@@ -127,6 +127,7 @@ 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, .{});

View File

@@ -117,6 +117,7 @@ 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, .{});

View File

@@ -94,12 +94,9 @@ pub const JsApi = struct {
pub const Meta = struct {
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 var class_id: bridge.ClassId = undefined;
pub const enumerable = false;
};
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 const weak = true;
pub const finalizer = bridge.finalizer(CustomEvent.deinit);
pub const enumerable = false;
};
pub const constructor = bridge.constructor(CustomEvent.init, .{});