harness/propertyHelper.js: Capture primordials that might be affected at runtime by verification

Ref https://github.com/tc39/test262/pull/4234#discussion_r1771684267
This commit is contained in:
Richard Gibson 2024-09-23 12:09:59 -04:00 committed by Philip Chimento
parent fcfb11da77
commit 07a2c2501e

View File

@ -17,6 +17,16 @@ defines:
// @ts-check // @ts-check
// Capture primordial functions and receiver-uncurried primordial methods that
// are used in verification but might be destroyed *by* that process itself.
var __isArray = Array.isArray;
var __defineProperty = Object.defineProperty;
var __join = Function.prototype.call.bind(Array.prototype.join);
var __push = Function.prototype.call.bind(Array.prototype.push);
var __hasOwnProperty = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
var __propertyIsEnumerable = Function.prototype.call.bind(Object.prototype.propertyIsEnumerable);
var nonIndexNumericPropertyName = Math.pow(2, 32) - 1;
/** /**
* @param {object} obj * @param {object} obj
* @param {string|symbol} name * @param {string|symbol} name
@ -46,7 +56,7 @@ function verifyProperty(obj, name, desc, options) {
} }
assert( assert(
Object.prototype.hasOwnProperty.call(obj, name), __hasOwnProperty(obj, name),
"obj should have an own property " + nameStr "obj should have an own property " + nameStr
); );
@ -77,47 +87,48 @@ function verifyProperty(obj, name, desc, options) {
var failures = []; var failures = [];
if (Object.prototype.hasOwnProperty.call(desc, 'value')) { if (__hasOwnProperty(desc, 'value')) {
if (!isSameValue(desc.value, originalDesc.value)) { if (!isSameValue(desc.value, originalDesc.value)) {
failures.push("descriptor value should be " + desc.value); __push(failures, "descriptor value should be " + desc.value);
} }
if (!isSameValue(desc.value, obj[name])) { if (!isSameValue(desc.value, obj[name])) {
failures.push("object value should be " + desc.value); __push(failures, "object value should be " + desc.value);
} }
} }
if (Object.prototype.hasOwnProperty.call(desc, 'enumerable')) { if (__hasOwnProperty(desc, 'enumerable')) {
if (desc.enumerable !== originalDesc.enumerable || if (desc.enumerable !== originalDesc.enumerable ||
desc.enumerable !== isEnumerable(obj, name)) { desc.enumerable !== isEnumerable(obj, name)) {
failures.push('descriptor should ' + (desc.enumerable ? '' : 'not ') + 'be enumerable'); __push(failures, 'descriptor should ' + (desc.enumerable ? '' : 'not ') + 'be enumerable');
} }
} }
if (Object.prototype.hasOwnProperty.call(desc, 'writable')) { // Operations past this point are potentially destructive!
if (__hasOwnProperty(desc, 'writable')) {
if (desc.writable !== originalDesc.writable || if (desc.writable !== originalDesc.writable ||
desc.writable !== isWritable(obj, name)) { desc.writable !== isWritable(obj, name)) {
failures.push('descriptor should ' + (desc.writable ? '' : 'not ') + 'be writable'); __push(failures, 'descriptor should ' + (desc.writable ? '' : 'not ') + 'be writable');
} }
} }
if (Object.prototype.hasOwnProperty.call(desc, 'configurable')) { if (__hasOwnProperty(desc, 'configurable')) {
if (desc.configurable !== originalDesc.configurable || if (desc.configurable !== originalDesc.configurable ||
desc.configurable !== isConfigurable(obj, name)) { desc.configurable !== isConfigurable(obj, name)) {
failures.push('descriptor should ' + (desc.configurable ? '' : 'not ') + 'be configurable'); __push(failures, 'descriptor should ' + (desc.configurable ? '' : 'not ') + 'be configurable');
} }
} }
assert(!failures.length, failures.join('; ')); assert(!failures.length, __join(failures, '; '));
if (options && options.restore) { if (options && options.restore) {
Object.defineProperty(obj, name, originalDesc); __defineProperty(obj, name, originalDesc);
} }
return true; return true;
} }
function isConfigurable(obj, name) { function isConfigurable(obj, name) {
var hasOwnProperty = Object.prototype.hasOwnProperty;
try { try {
delete obj[name]; delete obj[name];
} catch (e) { } catch (e) {
@ -125,7 +136,7 @@ function isConfigurable(obj, name) {
throw new Test262Error("Expected TypeError, got " + e); throw new Test262Error("Expected TypeError, got " + e);
} }
} }
return !hasOwnProperty.call(obj, name); return !__hasOwnProperty(obj, name);
} }
function isEnumerable(obj, name) { function isEnumerable(obj, name) {
@ -143,9 +154,7 @@ function isEnumerable(obj, name) {
stringCheck = true; stringCheck = true;
} }
return stringCheck && return stringCheck && __hasOwnProperty(obj, name) && __propertyIsEnumerable(obj, name);
Object.prototype.hasOwnProperty.call(obj, name) &&
Object.prototype.propertyIsEnumerable.call(obj, name);
} }
function isSameValue(a, b) { function isSameValue(a, b) {
@ -155,13 +164,12 @@ function isSameValue(a, b) {
return a === b; return a === b;
} }
var __isArray = Array.isArray;
function isWritable(obj, name, verifyProp, value) { function isWritable(obj, name, verifyProp, value) {
var unlikelyValue = __isArray(obj) && name === "length" ? var unlikelyValue = __isArray(obj) && name === "length" ?
Math.pow(2, 32) - 1 : nonIndexNumericPropertyName :
"unlikelyValue"; "unlikelyValue";
var newValue = value || unlikelyValue; var newValue = value || unlikelyValue;
var hadValue = Object.prototype.hasOwnProperty.call(obj, name); var hadValue = __hasOwnProperty(obj, name);
var oldValue = obj[name]; var oldValue = obj[name];
var writeSucceeded; var writeSucceeded;