Changeset 206948 in webkit


Ignore:
Timestamp:
Oct 7, 2016 8:20:53 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

Object.freeze() and seal() should throw if PreventExtensions?() fails.
https://bugs.webkit.org/show_bug.cgi?id=163160

Reviewed by Saam Barati.

JSTests:

  • stress/object-freeze-with-proxy-preventExtensions.js: Added.
  • stress/object-seal-with-proxy-preventExtensions.js: Added.

Source/JavaScriptCore:

See https://tc39.github.io/ecma262/#sec-object.freeze,
https://tc39.github.io/ecma262/#sec-object.seal, and
https://tc39.github.io/ecma262/#sec-setintegritylevel. We need to call
preventExtensions first before proceeding to freeze / seal the object. If
preventExtensions fails, we should throw a TypeError.

  • runtime/ObjectConstructor.cpp:

(JSC::setIntegrityLevel):
(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):

Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r206846 r206948  
     12016-10-07  Mark Lam  <mark.lam@apple.com>
     2
     3        Object.freeze() and seal() should throw if [[PreventExtensions]]() fails.
     4        https://bugs.webkit.org/show_bug.cgi?id=163160
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/object-freeze-with-proxy-preventExtensions.js: Added.
     9        * stress/object-seal-with-proxy-preventExtensions.js: Added.
     10
    1112016-10-05  Yusuke Suzuki  <utatane.tea@gmail.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r206899 r206948  
     12016-10-07  Mark Lam  <mark.lam@apple.com>
     2
     3        Object.freeze() and seal() should throw if [[PreventExtensions]]() fails.
     4        https://bugs.webkit.org/show_bug.cgi?id=163160
     5
     6        Reviewed by Saam Barati.
     7
     8        See https://tc39.github.io/ecma262/#sec-object.freeze,
     9        https://tc39.github.io/ecma262/#sec-object.seal, and
     10        https://tc39.github.io/ecma262/#sec-setintegritylevel.  We need to call
     11        preventExtensions first before proceeding to freeze / seal the object.  If
     12        preventExtensions fails, we should throw a TypeError.
     13
     14        * runtime/ObjectConstructor.cpp:
     15        (JSC::setIntegrityLevel):
     16        (JSC::objectConstructorSeal):
     17        (JSC::objectConstructorFreeze):
     18
    1192016-10-06  Yusuke Suzuki  <utatane.tea@gmail.com>
    220
  • trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp

    r206778 r206948  
    472472}
    473473
     474enum class IntegrityLevel {
     475    Sealed,
     476    Frozen
     477};
     478
     479template<IntegrityLevel level>
     480bool setIntegrityLevel(ExecState* exec, VM& vm, JSObject* object)
     481{
     482    // See https://tc39.github.io/ecma262/#sec-setintegritylevel.
     483    auto scope = DECLARE_THROW_SCOPE(vm);
     484
     485    bool success = object->methodTable(vm)->preventExtensions(object, exec);
     486    RETURN_IF_EXCEPTION(scope, false);
     487    if (UNLIKELY(!success))
     488        return false;
     489
     490    PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
     491    object->methodTable(vm)->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     492    RETURN_IF_EXCEPTION(scope, false);
     493
     494    PropertyNameArray::const_iterator end = properties.end();
     495    for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
     496        Identifier propertyName = *iter;
     497        if (vm.propertyNames->isPrivateName(propertyName))
     498            continue;
     499
     500        PropertyDescriptor desc;
     501        if (level == IntegrityLevel::Sealed)
     502            desc.setConfigurable(false);
     503        else {
     504            if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
     505                continue;
     506
     507            if (desc.isDataDescriptor())
     508                desc.setWritable(false);
     509
     510            desc.setConfigurable(false);
     511        }
     512
     513        object->methodTable(vm)->defineOwnProperty(object, exec, propertyName, desc, true);
     514        RETURN_IF_EXCEPTION(scope, false);
     515    }
     516    return true;
     517}
     518   
    474519EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
    475520{
     
    488533    }
    489534
    490     // 2. For each named own property name P of O,
    491     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
    492     object->methodTable(vm)->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
    493     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    494     PropertyNameArray::const_iterator end = properties.end();
    495     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
    496         Identifier propertyName = *iter;
    497         if (exec->propertyNames().isPrivateName(propertyName))
    498             continue;
    499         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
    500         PropertyDescriptor desc;
    501         if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
    502             continue;
    503         // b. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
    504         desc.setConfigurable(false);
    505         // c. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
    506         object->methodTable(vm)->defineOwnProperty(object, exec, propertyName, desc, true);
    507         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    508     }
    509 
    510     // 3. Set the [[Extensible]] internal property of O to false.
    511     object->methodTable(vm)->preventExtensions(object, exec);
    512     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    513 
    514     // 4. Return O.
     535    bool success = setIntegrityLevel<IntegrityLevel::Sealed>(exec, vm, object);
     536    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     537    if (!success) {
     538        throwTypeError(exec, scope, ASCIILiteral("Unable to prevent extension in Object.seal"));
     539        return encodedJSValue();
     540    }
     541
    515542    return JSValue::encode(obj);
    516543}
     
    526553    }
    527554
    528     // 2. For each named own property name P of O,
    529     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
    530     object->methodTable(vm)->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
     555    bool success = setIntegrityLevel<IntegrityLevel::Frozen>(exec, vm, object);
    531556    RETURN_IF_EXCEPTION(scope, nullptr);
    532     PropertyNameArray::const_iterator end = properties.end();
    533     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
    534         Identifier propertyName = *iter;
    535         if (exec->propertyNames().isPrivateName(propertyName))
    536             continue;
    537         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
    538         PropertyDescriptor desc;
    539         if (!object->getOwnPropertyDescriptor(exec, propertyName, desc))
    540             continue;
    541         // b. If IsDataDescriptor(desc) is true, then
    542         // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false.
    543         if (desc.isDataDescriptor())
    544             desc.setWritable(false);
    545         // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
    546         desc.setConfigurable(false);
    547         // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
    548         object->methodTable(vm)->defineOwnProperty(object, exec, propertyName, desc, true);
    549         RETURN_IF_EXCEPTION(scope, nullptr);
    550     }
    551 
    552     // 3. Set the [[Extensible]] internal property of O to false.
    553     object->methodTable(vm)->preventExtensions(object, exec);
    554     RETURN_IF_EXCEPTION(scope, nullptr);
    555 
    556     // 4. Return O.
     557    if (!success)
     558        return throwTypeError(exec, scope, ASCIILiteral("Unable to prevent extension in Object.freeze"));
    557559    return object;
    558560}
Note: See TracChangeset for help on using the changeset viewer.