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']", "BinaryExpression[operator='instanceof'][right.name='Object']",
message: "Use `typeof` rather than `instanceof 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]", selector: "CallExpression[callee.name='assert'][arguments.length!=2]",
message: "`assert()` must always be invoked with two arguments.", message: "`assert()` must always be invoked with two arguments.",

View File

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

View File

@ -127,7 +127,7 @@ class WorkerMessageHandler {
// the `{Object, Array}.prototype` has been *incorrectly* extended. // the `{Object, Array}.prototype` has been *incorrectly* extended.
// //
// PLEASE NOTE: We do *not* want to slow down font parsing by adding // 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) => const buildMsg = (type, prop) =>
`The \`${type}.prototype\` contains unexpected enumerable property ` + `The \`${type}.prototype\` contains unexpected enumerable property ` +
`"${prop}", thus breaking e.g. \`for...in\` iteration of ${type}s.`; `"${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"/> // <setProperty ref="$data.Main.Help.LastName" target="assist.toolTip"/>
// </field> // </field>
if (!formNode.hasOwnProperty("setProperty")) { if (!Object.hasOwn(formNode, "setProperty")) {
return; return;
} }
@ -265,7 +265,7 @@ class Binder {
continue; continue;
} }
if (!targetNode.hasOwnProperty($content)) { if (!Object.hasOwn(targetNode, $content)) {
warn(`XFA - Invalid node to use in setProperty`); warn(`XFA - Invalid node to use in setProperty`);
continue; continue;
} }
@ -285,8 +285,8 @@ class Binder {
// </field> // </field>
if ( if (
!formNode.hasOwnProperty("items") || !Object.hasOwn(formNode, "items") ||
!formNode.hasOwnProperty("bindItems") || !Object.hasOwn(formNode, "bindItems") ||
formNode.bindItems.isEmpty() formNode.bindItems.isEmpty()
) { ) {
return; return;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2575,7 +2575,7 @@ class WorkerTransport {
this.#pagePromises.clear(); this.#pagePromises.clear();
this.#pageRefCache.clear(); this.#pageRefCache.clear();
// Allow `AnnotationStorage`-related clean-up when destroying the document. // Allow `AnnotationStorage`-related clean-up when destroying the document.
if (this.hasOwnProperty("annotationStorage")) { if (Object.hasOwn(this, "annotationStorage")) {
this.annotationStorage.resetModified(); this.annotationStorage.resetModified();
} }
// We also need to wait for the worker to finish its long running tasks. // 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) { for (const option of element.children) {
if (option.attributes.value === storedData.value) { if (option.attributes.value === storedData.value) {
option.attributes.selected = true; option.attributes.selected = true;
} else if (option.attributes.hasOwnProperty("selected")) { } else if (Object.hasOwn(option.attributes, "selected")) {
delete option.attributes.selected; delete option.attributes.selected;
} }
} }

View File

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