Changeset 215272 in webkit


Ignore:
Timestamp:
Apr 12, 2017 10:35:31 AM (7 years ago)
Author:
msaboff@apple.com
Message:

Implement Object.isFrozen() and Object.isSealed() per ECMA spec
https://bugs.webkit.org/show_bug.cgi?id=170753

Reviewed by Mark Lam.

JSTests:

Added JSC baseline and enabled defineIndexProperty test.

Note that JSC differs from Chakra in that a JSC doesn't use indexed
properties placed on the Array prototype when sorting the indexed
properties of an Object. This is behavior is considered undefined
in the standard.

  • ChakraCore.yaml:
  • ChakraCore/test/es5/defineIndexProperty.baseline-jsc: Added.

Source/JavaScriptCore:

  • runtime/ObjectConstructor.cpp:

(JSC::testIntegrityLevel): Added local helper as described in the ECMA standard.

(JSC::objectConstructorSeal):
(JSC::objectConstructorFreeze):
Eliminated incomplete special handling of JSFinalObjects.

(JSC::objectConstructorIsSealed):
(JSC::objectConstructorIsFrozen):
Refactored to use the new testIntegrityLevel() helper.

Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChakraCore.yaml

    r215133 r215272  
    14431443  cmd: runChakra :baseline, "NoException", "defineProperty.baseline", ["../UnitTestFramework/UnitTestFramework.js"]
    14441444- path: ChakraCore/test/es5/defineIndexProperty.js
    1445   # Differences in Obj.seal, Obj.frozen and sort.
    1446   cmd: runChakra :skip, "NoException", "defineIndexProperty.baseline", []
     1445  cmd: runChakra :baseline, "NoException", "defineIndexProperty.baseline-jsc", []
    14471446- path: ChakraCore/test/es5/enumerable.js
    14481447  cmd: runChakra :baseline, "NoException", "enumerable.baseline-jsc", []
  • trunk/JSTests/ChangeLog

    r215235 r215272  
     12017-04-11  Michael Saboff  <msaboff@apple.com>
     2
     3        Implement Object.isFrozen() and Object.isSealed() per ECMA spec
     4        https://bugs.webkit.org/show_bug.cgi?id=170753
     5
     6        Reviewed by Mark Lam.
     7
     8        Added JSC baseline and enabled defineIndexProperty test.
     9
     10        Note that JSC differs from Chakra in that a JSC doesn't use indexed
     11        properties placed on the Array prototype when sorting the indexed
     12        properties of an Object.  This is behavior is considered undefined
     13        in the standard.
     14
     15        * ChakraCore.yaml:
     16        * ChakraCore/test/es5/defineIndexProperty.baseline-jsc: Added.
     17
    1182017-04-11  Joseph Pecoraro  <pecoraro@apple.com>
    219
  • trunk/Source/JavaScriptCore/ChangeLog

    r215270 r215272  
     12017-04-12  Michael Saboff  <msaboff@apple.com>
     2
     3        Implement Object.isFrozen() and Object.isSealed() per ECMA spec
     4        https://bugs.webkit.org/show_bug.cgi?id=170753
     5
     6        Reviewed by Mark Lam.
     7
     8        * runtime/ObjectConstructor.cpp:
     9        (JSC::testIntegrityLevel): Added local helper as described in the ECMA standard.
     10
     11        (JSC::objectConstructorSeal):
     12        (JSC::objectConstructorFreeze):
     13        Eliminated incomplete special handling of JSFinalObjects.
     14
     15        (JSC::objectConstructorIsSealed):
     16        (JSC::objectConstructorIsFrozen):
     17        Refactored to use the new testIntegrityLevel() helper.
     18
    1192017-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
    220
  • trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp

    r215234 r215272  
    547547    return true;
    548548}
    549    
     549
     550template<IntegrityLevel level>
     551bool testIntegrityLevel(ExecState* exec, VM& vm, JSObject* object)
     552{
     553    auto scope = DECLARE_THROW_SCOPE(vm);
     554
     555    // 1. Assert: Type(O) is Object.
     556    // 2. Assert: level is either "sealed" or "frozen".
     557
     558    // 3. Let status be ?IsExtensible(O).
     559    bool status = object->isExtensible(exec);
     560    RETURN_IF_EXCEPTION(scope, { });
     561
     562    // 4. If status is true, return false.
     563    if (status)
     564        return false;
     565
     566    // 6. Let keys be ? O.[[OwnPropertyKeys]]().
     567    PropertyNameArray keys(exec, PropertyNameMode::StringsAndSymbols);
     568    object->methodTable(vm)->getOwnPropertyNames(object, exec, keys, EnumerationMode(DontEnumPropertiesMode::Include));
     569    RETURN_IF_EXCEPTION(scope, { });
     570
     571    // 7. For each element k of keys, do
     572    PropertyNameArray::const_iterator end = keys.end();
     573    for (PropertyNameArray::const_iterator iter = keys.begin(); iter != end; ++iter) {
     574        Identifier propertyName = *iter;
     575        if (vm.propertyNames->isPrivateName(propertyName))
     576            continue;
     577
     578        // a. Let currentDesc be ? O.[[GetOwnProperty]](k)
     579        PropertyDescriptor desc;
     580        bool didGetDescriptor = object->getOwnPropertyDescriptor(exec, propertyName, desc);
     581        RETURN_IF_EXCEPTION(scope, { });
     582
     583        // b. If currentDesc is not undefined, then
     584        if (!didGetDescriptor)
     585            continue;
     586
     587        // i. If currentDesc.[[Configurable]] is true, return false.
     588        if (desc.configurable())
     589            return false;
     590
     591        // ii. If level is "frozen" and IsDataDescriptor(currentDesc) is true, then
     592        // 1. If currentDesc.[[Writable]] is true, return false.
     593        if (level == IntegrityLevel::Frozen && desc.isDataDescriptor() && desc.writable())
     594            return false;
     595    }
     596
     597    return true;
     598}
     599
    550600EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
    551601{
     
    559609    JSObject* object = asObject(obj);
    560610
    561     if (isJSFinalObject(object)) {
    562         object->seal(vm);
    563         return JSValue::encode(obj);
    564     }
    565 
    566611    bool success = setIntegrityLevel<IntegrityLevel::Sealed>(exec, vm, object);
    567612    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     
    578623    VM& vm = exec->vm();
    579624    auto scope = DECLARE_THROW_SCOPE(vm);
    580 
    581     if (isJSFinalObject(object) && !hasIndexedProperties(object->indexingType())) {
    582         object->freeze(vm);
    583         return object;
    584     }
    585625
    586626    bool success = setIntegrityLevel<IntegrityLevel::Frozen>(exec, vm, object);
     
    618658{
    619659    VM& vm = exec->vm();
    620     auto scope = DECLARE_THROW_SCOPE(vm);
    621660
    622661    // 1. If Type(O) is not Object, return true.
     
    626665    JSObject* object = asObject(obj);
    627666
    628     if (isJSFinalObject(object))
    629         return JSValue::encode(jsBoolean(object->isSealed(vm)));
    630 
    631     // 2. For each named own property name P of O,
    632     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
    633     object->methodTable(vm)->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
    634     RETURN_IF_EXCEPTION(scope, { });
    635     PropertyNameArray::const_iterator end = properties.end();
    636     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
    637         Identifier propertyName = *iter;
    638         if (vm.propertyNames->isPrivateName(propertyName))
    639             continue;
    640         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
    641         PropertyDescriptor desc;
    642         bool didGetDescriptor = object->getOwnPropertyDescriptor(exec, propertyName, desc);
    643         RETURN_IF_EXCEPTION(scope, { });
    644         if (!didGetDescriptor)
    645             continue;
    646         // b. If desc.[[Configurable]] is true, then return false.
    647         if (desc.configurable())
    648             return JSValue::encode(jsBoolean(false));
    649     }
    650 
    651     // 3. If the [[Extensible]] internal property of O is false, then return true.
    652     // 4. Otherwise, return false.
    653     bool isExtensible = object->isExtensible(exec);
    654     RETURN_IF_EXCEPTION(scope, { });
    655     return JSValue::encode(jsBoolean(!isExtensible));
     667    // 2. Return ? TestIntegrityLevel(O, "sealed").
     668    return JSValue::encode(jsBoolean(testIntegrityLevel<IntegrityLevel::Sealed>(exec, vm, object)));
    656669}
    657670
     
    659672{
    660673    VM& vm = exec->vm();
    661     auto scope = DECLARE_THROW_SCOPE(vm);
    662674
    663675    // 1. If Type(O) is not Object, return true.
     
    667679    JSObject* object = asObject(obj);
    668680
    669     if (isJSFinalObject(object))
    670         return JSValue::encode(jsBoolean(object->isFrozen(vm)));
    671 
    672     // 2. For each named own property name P of O,
    673     PropertyNameArray properties(exec, PropertyNameMode::StringsAndSymbols);
    674     object->methodTable(vm)->getOwnPropertyNames(object, exec, properties, EnumerationMode(DontEnumPropertiesMode::Include));
    675     RETURN_IF_EXCEPTION(scope, { });
    676     PropertyNameArray::const_iterator end = properties.end();
    677     for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
    678         Identifier propertyName = *iter;
    679         if (vm.propertyNames->isPrivateName(propertyName))
    680             continue;
    681         // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
    682         PropertyDescriptor desc;
    683         bool didGetDescriptor = object->getOwnPropertyDescriptor(exec, propertyName, desc);
    684         RETURN_IF_EXCEPTION(scope, { });
    685         if (!didGetDescriptor)
    686             continue;
    687         // b. If IsDataDescriptor(desc) is true then
    688         // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false.
    689         if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable())
    690             return JSValue::encode(jsBoolean(false));
    691     }
    692 
    693     // 3. If the [[Extensible]] internal property of O is false, then return true.
    694     // 4. Otherwise, return false.
    695     bool isExtensible = object->isExtensible(exec);
    696     RETURN_IF_EXCEPTION(scope, { });
    697     return JSValue::encode(jsBoolean(!isExtensible));
     681    // 2. Return ? TestIntegrityLevel(O, "frozen").
     682    return JSValue::encode(jsBoolean(testIntegrityLevel<IntegrityLevel::Frozen>(exec, vm, object)));
    698683}
    699684
Note: See TracChangeset for help on using the changeset viewer.