Replace all Object.prototype.hasOwnProperty usage with Object.hasOwn

The newer `Object.hasOwn` method is intended as a replacement for `Object.prototype.hasOwnProperty`, since that one may be problematical; please see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#problematic_cases_for_hasownproperty

To ensure that `Object.hasOwn` is used in the future, the ESLint "no-restricted-syntax" rule is extended to catch the old method.
This commit is contained in:
Jonas Jenwald 2026-04-02 13:36:57 +02:00
parent f09b03c062
commit cbfe2abc53
19 changed files with 28 additions and 23 deletions

View File

@ -299,6 +299,11 @@ export default [
"BinaryExpression[operator='instanceof'][right.name='Object']",
message: "Use `typeof` rather than `instanceof Object`.",
},
{
selector: "MemberExpression[property.name='hasOwnProperty']",
message:
"Use `Object.hasOwn` rather than `Object.prototype.hasOwnProperty`.",
},
{
selector: "CallExpression[callee.name='assert'][arguments.length!=2]",
message: "`assert()` must always be invoked with two arguments.",

View File

@ -718,7 +718,7 @@ class Catalog {
getDestination(id) {
// Avoid extra lookup/parsing when all destinations are already available.
if (this.hasOwnProperty("destinations")) {
if (Object.hasOwn(this, "destinations")) {
return this.destinations[id] ?? null;
}

View File

@ -127,7 +127,7 @@ class WorkerMessageHandler {
// the `{Object, Array}.prototype` has been *incorrectly* extended.
//
// PLEASE NOTE: We do *not* want to slow down font parsing by adding
// `hasOwnProperty` checks all over the code-base.
// `Object.hasOwn` checks all over the code-base.
const buildMsg = (type, prop) =>
`The \`${type}.prototype\` contains unexpected enumerable property ` +
`"${prop}", thus breaking e.g. \`for...in\` iteration of ${type}s.`;

View File

@ -180,7 +180,7 @@ class Binder {
// <setProperty ref="$data.Main.Help.LastName" target="assist.toolTip"/>
// </field>
if (!formNode.hasOwnProperty("setProperty")) {
if (!Object.hasOwn(formNode, "setProperty")) {
return;
}
@ -265,7 +265,7 @@ class Binder {
continue;
}
if (!targetNode.hasOwnProperty($content)) {
if (!Object.hasOwn(targetNode, $content)) {
warn(`XFA - Invalid node to use in setProperty`);
continue;
}
@ -285,8 +285,8 @@ class Binder {
// </field>
if (
!formNode.hasOwnProperty("items") ||
!formNode.hasOwnProperty("bindItems") ||
!Object.hasOwn(formNode, "items") ||
!Object.hasOwn(formNode, "bindItems") ||
formNode.bindItems.isEmpty()
) {
return;

View File

@ -97,7 +97,7 @@ class Builder {
this._addNamespacePrefix(prefixes);
}
if (attributes.hasOwnProperty($nsAttributes)) {
if (Object.hasOwn(attributes, $nsAttributes)) {
// Only support xfa-data namespace.
const dataTemplate = NamespaceSetUp.datasets;
const nsAttrs = attributes[$nsAttributes];

View File

@ -1355,7 +1355,7 @@ class Zpl extends XFAObject {
class ConfigNamespace {
static [$buildXFAObject](name, attributes) {
if (ConfigNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(ConfigNamespace, name)) {
return ConfigNamespace[name](attributes);
}
return undefined;

View File

@ -144,7 +144,7 @@ class XsdConnection extends XFAObject {
class ConnectionSetNamespace {
static [$buildXFAObject](name, attributes) {
if (ConnectionSetNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(ConnectionSetNamespace, name)) {
return ConnectionSetNamespace[name](attributes);
}
return undefined;

View File

@ -57,7 +57,7 @@ class Datasets extends XFAObject {
class DatasetsNamespace {
static [$buildXFAObject](name, attributes) {
if (DatasetsNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(DatasetsNamespace, name)) {
return DatasetsNamespace[name](attributes);
}
return undefined;

View File

@ -383,7 +383,7 @@ function toStyle(node, ...names) {
if (value === null) {
continue;
}
if (converters.hasOwnProperty(name)) {
if (Object.hasOwn(converters, name)) {
converters[name](node, style);
continue;
}

View File

@ -239,7 +239,7 @@ class TypeFaces extends XFAObject {
class LocaleSetNamespace {
static [$buildXFAObject](name, attributes) {
if (LocaleSetNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(LocaleSetNamespace, name)) {
return LocaleSetNamespace[name](attributes);
}
return undefined;

View File

@ -26,7 +26,7 @@ class Signature extends XFAObject {
class SignatureNamespace {
static [$buildXFAObject](name, attributes) {
if (SignatureNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(SignatureNamespace, name)) {
return SignatureNamespace[name](attributes);
}
return undefined;

View File

@ -26,7 +26,7 @@ class Stylesheet extends XFAObject {
class StylesheetNamespace {
static [$buildXFAObject](name, attributes) {
if (StylesheetNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(StylesheetNamespace, name)) {
return StylesheetNamespace[name](attributes);
}
return undefined;

View File

@ -6132,7 +6132,7 @@ class Variables extends XFAObject {
class TemplateNamespace {
static [$buildXFAObject](name, attributes) {
if (TemplateNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(TemplateNamespace, name)) {
const node = TemplateNamespace[name](attributes);
node[$setSetAttributes](attributes);
return node;

View File

@ -40,7 +40,7 @@ class Xdp extends XFAObject {
class XdpNamespace {
static [$buildXFAObject](name, attributes) {
if (XdpNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(XdpNamespace, name)) {
return XdpNamespace[name](attributes);
}
return undefined;

View File

@ -171,7 +171,7 @@ class XFAObject {
[$onChildCheck](child) {
return (
this.hasOwnProperty(child[$nodeName]) &&
Object.hasOwn(this, child[$nodeName]) &&
child[$namespaceId] === this[$namespaceId]
);
}
@ -240,7 +240,7 @@ class XFAObject {
}
[$hasSettableValue]() {
return this.hasOwnProperty("value");
return Object.hasOwn(this, "value");
}
[$setValue](_) {}
@ -817,7 +817,7 @@ class XmlObject extends XFAObject {
for (const [attrName, value] of Object.entries(attributes)) {
map.set(attrName, new XFAAttribute(this, attrName, value));
}
if (attributes.hasOwnProperty($nsAttributes)) {
if (Object.hasOwn(attributes, $nsAttributes)) {
// XFA attributes.
const dataNode = attributes[$nsAttributes].xfa.dataNode;
if (dataNode !== undefined) {

View File

@ -530,7 +530,7 @@ class Ul extends XhtmlObject {
class XhtmlNamespace {
static [$buildXFAObject](name, attributes) {
if (XhtmlNamespace.hasOwnProperty(name)) {
if (Object.hasOwn(XhtmlNamespace, name)) {
return XhtmlNamespace[name](attributes);
}
return undefined;

View File

@ -2575,7 +2575,7 @@ class WorkerTransport {
this.#pagePromises.clear();
this.#pageRefCache.clear();
// Allow `AnnotationStorage`-related clean-up when destroying the document.
if (this.hasOwnProperty("annotationStorage")) {
if (Object.hasOwn(this, "annotationStorage")) {
this.annotationStorage.resetModified();
}
// We also need to wait for the worker to finish its long running tasks.

View File

@ -86,7 +86,7 @@ class XfaLayer {
for (const option of element.children) {
if (option.attributes.value === storedData.value) {
option.attributes.selected = true;
} else if (option.attributes.hasOwnProperty("selected")) {
} else if (Object.hasOwn(option.attributes, "selected")) {
delete option.attributes.selected;
}
}

View File

@ -77,7 +77,7 @@ class Field extends PDFObject {
this._fillColor = data.fillColor || ["T"];
this._isChoice = Array.isArray(data.items);
this._items = data.items || [];
this._hasValue = data.hasOwnProperty("value");
this._hasValue = Object.hasOwn(data, "value");
this._page = data.page || 0;
this._strokeColor = data.strokeColor || ["G", 0];
this._textColor = data.textColor || ["G", 0];