From 7e04e8270414ea2aff712383d81328d0e2591c67 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Wed, 29 Mar 2023 10:29:24 -0400 Subject: [PATCH 1/2] Change approach to shadowing non-writable properties --- big.js | 30 +++++++++++++++++++++++++++--- big.mjs | 30 +++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/big.js b/big.js index 7743ddd..fb55576 100644 --- a/big.js +++ b/big.js @@ -111,7 +111,16 @@ // Retain a reference to this Big constructor. // Shadow Big.prototype.constructor which points to Object. - x.constructor = Big; + if (typeof Object.defineProperty === 'function') { + // If the Object prototype is frozen, the "constructor" property is non-writable. This means that any objects which inherit this + // property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not + // using strict mode, attempting that will be silently ignored. + // However, we can still explicitly shadow the prototype's non-writable property by defining a new property on this object. + Object.defineProperty(x, 'constructor', { value: Big }); + } else { + // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. + x.constructor = Big; + } } Big.prototype = P; @@ -960,7 +969,7 @@ * Big.PE, or a negative exponent equal to or less than Big.NE. * Omit the sign for negative zero. */ - P.toJSON = P.toString = function () { + function toString() { var x = this, Big = x.constructor; return stringify(x, x.e <= Big.NE || x.e >= Big.PE, !!x.c[0]); @@ -1011,7 +1020,7 @@ * Big.PE, or a negative exponent equal to or less than Big.NE. * Include the sign for negative zero. */ - P.valueOf = function () { + function valueOf() { var x = this, Big = x.constructor; if (Big.strict === true) { @@ -1021,6 +1030,21 @@ }; + P.toJSON = toString; + if (typeof Object.defineProperty === 'function') { + // If the Object prototype is frozen, the "toString" and "valueOf" properties are non-writable. This means that any objects which + // inherit these property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an + // error. If not using strict mode, attempting that will be silently ignored. + // However, we can still explicitly shadow the prototype's non-writable properties by defining new properties on this object. + Object.defineProperty(P, 'toString', { value: toString }); + Object.defineProperty(P, 'valueOf', { value: valueOf }); + } else { + // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. + P.toString = toString; + P.valueOf = valueOf; + } + + // Export diff --git a/big.mjs b/big.mjs index 079b743..2c0c2ae 100644 --- a/big.mjs +++ b/big.mjs @@ -108,7 +108,16 @@ function _Big_() { // Retain a reference to this Big constructor. // Shadow Big.prototype.constructor which points to Object. - x.constructor = Big; + if (typeof Object.defineProperty === 'function') { + // If the Object prototype is frozen, the "constructor" property is non-writable. This means that any objects which inherit this + // property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not + // using strict mode, attempting that will be silently ignored. + // However, we can still explicitly shadow the prototype's non-writable property by defining a new property on this object. + Object.defineProperty(x, 'constructor', { value: Big }); + } else { + // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. + x.constructor = Big; + } } Big.prototype = P; @@ -957,7 +966,7 @@ P.toFixed = function (dp, rm) { * Big.PE, or a negative exponent equal to or less than Big.NE. * Omit the sign for negative zero. */ -P[Symbol.for('nodejs.util.inspect.custom')] = P.toJSON = P.toString = function () { +function toString() { var x = this, Big = x.constructor; return stringify(x, x.e <= Big.NE || x.e >= Big.PE, !!x.c[0]); @@ -1008,7 +1017,7 @@ P.toPrecision = function (sd, rm) { * Big.PE, or a negative exponent equal to or less than Big.NE. * Include the sign for negative zero. */ -P.valueOf = function () { +function valueOf() { var x = this, Big = x.constructor; if (Big.strict === true) { @@ -1018,6 +1027,21 @@ P.valueOf = function () { }; +P[Symbol.for('nodejs.util.inspect.custom')] = P.toJSON = toString; +if (typeof Object.defineProperty === 'function') { + // If the Object prototype is frozen, the "toString" and "valueOf" properties are non-writable. This means that any objects which + // inherit these property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an + // error. If not using strict mode, attempting that will be silently ignored. + // However, we can still explicitly shadow the prototype's non-writable properties by defining new properties on this object. + Object.defineProperty(P, 'toString', { value: toString }); + Object.defineProperty(P, 'valueOf', { value: valueOf }); +} else { + // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. + P.toString = toString; + P.valueOf = valueOf; +} + + // Export From 13284f9b2e74c2396b9ff5c5f6bd93958b942ece Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Wed, 29 Mar 2023 10:51:52 -0400 Subject: [PATCH 2/2] Remove fallback to assignment for ES module --- big.mjs | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/big.mjs b/big.mjs index 2c0c2ae..5932c2c 100644 --- a/big.mjs +++ b/big.mjs @@ -108,16 +108,11 @@ function _Big_() { // Retain a reference to this Big constructor. // Shadow Big.prototype.constructor which points to Object. - if (typeof Object.defineProperty === 'function') { - // If the Object prototype is frozen, the "constructor" property is non-writable. This means that any objects which inherit this - // property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not - // using strict mode, attempting that will be silently ignored. - // However, we can still explicitly shadow the prototype's non-writable property by defining a new property on this object. - Object.defineProperty(x, 'constructor', { value: Big }); - } else { - // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. - x.constructor = Big; - } + // If the Object prototype is frozen, the "constructor" property is non-writable. This means that any objects which inherit this + // property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not + // using strict mode, attempting that will be silently ignored. + // However, we can still explicitly shadow the prototype's non-writable property by defining a new property on this object. + Object.defineProperty(x, 'constructor', { value: Big }); } Big.prototype = P; @@ -966,7 +961,7 @@ P.toFixed = function (dp, rm) { * Big.PE, or a negative exponent equal to or less than Big.NE. * Omit the sign for negative zero. */ -function toString() { +var toString = P[Symbol.for('nodejs.util.inspect.custom')] = function () { var x = this, Big = x.constructor; return stringify(x, x.e <= Big.NE || x.e >= Big.PE, !!x.c[0]); @@ -1027,19 +1022,13 @@ function valueOf() { }; -P[Symbol.for('nodejs.util.inspect.custom')] = P.toJSON = toString; -if (typeof Object.defineProperty === 'function') { - // If the Object prototype is frozen, the "toString" and "valueOf" properties are non-writable. This means that any objects which - // inherit these property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an - // error. If not using strict mode, attempting that will be silently ignored. - // However, we can still explicitly shadow the prototype's non-writable properties by defining new properties on this object. - Object.defineProperty(P, 'toString', { value: toString }); - Object.defineProperty(P, 'valueOf', { value: valueOf }); -} else { - // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator. - P.toString = toString; - P.valueOf = valueOf; -} +P.toJSON = toString; +// If the Object prototype is frozen, the "toString" and "valueOf" properties are non-writable. This means that any objects which +// inherit these property cannot have the property changed using an assignment. If using strict mode, attempting that will cause an +// error. If not using strict mode, attempting that will be silently ignored. +// However, we can still explicitly shadow the prototype's non-writable properties by defining new properties on this object. +Object.defineProperty(P, 'toString', { value: toString }); +Object.defineProperty(P, 'valueOf', { value: valueOf }); // Export