123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- // Copyright (C) 2017 Ecma International. All rights reserved.
- // This code is governed by the BSD license found in the LICENSE file.
- /*---
- description: |
- Collection of functions used to safely verify the correctness of
- property descriptors.
- ---*/
- function verifyProperty(obj, name, desc, options) {
- assert(
- arguments.length > 2,
- 'verifyProperty should receive at least 3 arguments: obj, name, and descriptor'
- );
- var originalDesc = Object.getOwnPropertyDescriptor(obj, name);
- var nameStr = String(name);
- // Allows checking for undefined descriptor if it's explicitly given.
- if (desc === undefined) {
- assert.sameValue(
- originalDesc,
- undefined,
- "obj['" + nameStr + "'] descriptor should be undefined"
- );
- // desc and originalDesc are both undefined, problem solved;
- return true;
- }
- assert(
- Object.prototype.hasOwnProperty.call(obj, name),
- "obj should have an own property " + nameStr
- );
- assert.notSameValue(
- desc,
- null,
- "The desc argument should be an object or undefined, null"
- );
- assert.sameValue(
- typeof desc,
- "object",
- "The desc argument should be an object or undefined, " + String(desc)
- );
- var failures = [];
- if (Object.prototype.hasOwnProperty.call(desc, 'value')) {
- if (desc.value !== originalDesc.value) {
- failures.push("descriptor value should be " + desc.value);
- }
- }
- if (Object.prototype.hasOwnProperty.call(desc, 'enumerable')) {
- if (desc.enumerable !== originalDesc.enumerable ||
- desc.enumerable !== isEnumerable(obj, name)) {
- failures.push('descriptor should ' + (desc.enumerable ? '' : 'not ') + 'be enumerable');
- }
- }
- if (Object.prototype.hasOwnProperty.call(desc, 'writable')) {
- if (desc.writable !== originalDesc.writable ||
- desc.writable !== isWritable(obj, name)) {
- failures.push('descriptor should ' + (desc.writable ? '' : 'not ') + 'be writable');
- }
- }
- if (Object.prototype.hasOwnProperty.call(desc, 'configurable')) {
- if (desc.configurable !== originalDesc.configurable ||
- desc.configurable !== isConfigurable(obj, name)) {
- failures.push('descriptor should ' + (desc.configurable ? '' : 'not ') + 'be configurable');
- }
- }
- assert(!failures.length, failures.join('; '));
- if (options && options.restore) {
- Object.defineProperty(obj, name, originalDesc);
- }
- return true;
- }
- function isConfigurable(obj, name) {
- try {
- delete obj[name];
- } catch (e) {
- if (!(e instanceof TypeError)) {
- $ERROR("Expected TypeError, got " + e);
- }
- }
- return !Object.prototype.hasOwnProperty.call(obj, name);
- }
- function isEnumerable(obj, name) {
- var stringCheck = false;
- if (typeof name === "string") {
- for (var x in obj) {
- if (x === name) {
- stringCheck = true;
- break;
- }
- }
- } else {
- // skip it if name is not string, works for Symbol names.
- stringCheck = true;
- }
- return stringCheck &&
- Object.prototype.hasOwnProperty.call(obj, name) &&
- Object.prototype.propertyIsEnumerable.call(obj, name);
- }
- function isEqualTo(obj, name, expectedValue) {
- var actualValue = obj[name];
- return assert._isSameValue(actualValue, expectedValue);
- }
- function isWritable(obj, name, verifyProp, value) {
- var newValue = value || "unlikelyValue";
- var hadValue = Object.prototype.hasOwnProperty.call(obj, name);
- var oldValue = obj[name];
- var writeSucceeded;
- try {
- obj[name] = newValue;
- } catch (e) {
- if (!(e instanceof TypeError)) {
- $ERROR("Expected TypeError, got " + e);
- }
- }
- writeSucceeded = isEqualTo(obj, verifyProp || name, newValue);
- // Revert the change only if it was successful (in other cases, reverting
- // is unnecessary and may trigger exceptions for certain property
- // configurations)
- if (writeSucceeded) {
- if (hadValue) {
- obj[name] = oldValue;
- } else {
- delete obj[name];
- }
- }
- return writeSucceeded;
- }
- function verifyEqualTo(obj, name, value) {
- if (!isEqualTo(obj, name, value)) {
- $ERROR("Expected obj[" + String(name) + "] to equal " + value +
- ", actually " + obj[name]);
- }
- }
- function verifyWritable(obj, name, verifyProp, value) {
- if (!verifyProp) {
- assert(Object.getOwnPropertyDescriptor(obj, name).writable,
- "Expected obj[" + String(name) + "] to have writable:true.");
- }
- if (!isWritable(obj, name, verifyProp, value)) {
- $ERROR("Expected obj[" + String(name) + "] to be writable, but was not.");
- }
- }
- function verifyNotWritable(obj, name, verifyProp, value) {
- if (!verifyProp) {
- assert(!Object.getOwnPropertyDescriptor(obj, name).writable,
- "Expected obj[" + String(name) + "] to have writable:false.");
- }
- if (isWritable(obj, name, verifyProp)) {
- $ERROR("Expected obj[" + String(name) + "] NOT to be writable, but was.");
- }
- }
- function verifyEnumerable(obj, name) {
- assert(Object.getOwnPropertyDescriptor(obj, name).enumerable,
- "Expected obj[" + String(name) + "] to have enumerable:true.");
- if (!isEnumerable(obj, name)) {
- $ERROR("Expected obj[" + String(name) + "] to be enumerable, but was not.");
- }
- }
- function verifyNotEnumerable(obj, name) {
- assert(!Object.getOwnPropertyDescriptor(obj, name).enumerable,
- "Expected obj[" + String(name) + "] to have enumerable:false.");
- if (isEnumerable(obj, name)) {
- $ERROR("Expected obj[" + String(name) + "] NOT to be enumerable, but was.");
- }
- }
- function verifyConfigurable(obj, name) {
- assert(Object.getOwnPropertyDescriptor(obj, name).configurable,
- "Expected obj[" + String(name) + "] to have configurable:true.");
- if (!isConfigurable(obj, name)) {
- $ERROR("Expected obj[" + String(name) + "] to be configurable, but was not.");
- }
- }
- function verifyNotConfigurable(obj, name) {
- assert(!Object.getOwnPropertyDescriptor(obj, name).configurable,
- "Expected obj[" + String(name) + "] to have configurable:false.");
- if (isConfigurable(obj, name)) {
- $ERROR("Expected obj[" + String(name) + "] NOT to be configurable, but was.");
- }
- }
|