Ignore:
Timestamp:
Mar 19, 2017, 10:45:39 AM (8 years ago)
Author:
Chris Dumez
Message:

const location = "foo" throws in a worker
https://bugs.webkit.org/show_bug.cgi?id=169839

Reviewed by Mark Lam.

JSTests:

  • ChakraCore/test/es6/letconst_global_shadow_builtins_nonconfigurable.baseline-jsc:

Update expected jsc result now that we throw a SyntaxError when trying to shadow undefined
with a let variable. We used not to throw because the value is undefined but this was not
as per EcmaScript. Both Firefox and Chrome throw in this case.

  • stress/global-lexical-redeclare-variable.js:

(catch):
Update test that defines a non-configurable 'zoo' property on the global object and then
expected shadowing it with a 'let zoo' variable to work because its value was undefined.
This was not as per EcmaScript spec and both Firefox and Chrome throw in this case.

Source/JavaScriptCore:

Our HasRestrictedGlobalProperty check in JSC was slightly wrong, causing us
to sometimes throw a Syntax exception when we shouldn't when declaring a
const/let variable and sometimes not throw an exception when we should have.

This aligns our behavior with ES6, Firefox and Chrome.

  • runtime/ProgramExecutable.cpp:

(JSC::hasRestrictedGlobalProperty):
(JSC::ProgramExecutable::initializeGlobalProperties):
Rewrite hasRestrictedGlobalProperty logic as per the EcmaScript spec:

In particular, they were 2 issues:

  • We should throw a SyntaxError if hasProperty() returned true but getOwnProperty() would fail to return a descriptor. This would happen for properties that are not OWN properties, but defined somewhere in the prototype chain. The spec does not say to use hasProperty(), only getOwnProperty() and says we should return false if getOwnProperty() does not return a descriptor. This is what we do now.
  • We would fail to throw when declaring a let/const variable that shadows an own property whose value is undefined. This is because the previous code was explicitly checking for this case. I believe this was a misinterpretation of ES6 which says: """ Let desc be O.GetOwnProperty(P). If desc is undefined, return false. """ We should check that desc is undefined, not desc.value. This is now fixed.

LayoutTests:

  • fast/dom/window-const-variable-shadowing-expected.txt: Added.
  • fast/dom/window-const-variable-shadowing.html: Added.
  • fast/workers/const-location-variable-expected.txt: Added.
  • fast/workers/const-location-variable.html: Added.
  • fast/workers/resources/worker-const-location.js: Added.

Add layout test coverage for behavior changes. Those tests pass in Firefox and Chrome.

  • js/dom/const-expected.txt:
  • js/dom/const.html:

Update test which wrongly expected a let variable not to be able to shadow a
window named property. This test was failing in Chrome and Firefox. The reason
this does not throw is because window named properties are not on the window
object, they are on the WindowProperties object in the Window prototype chain.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp

    r209897 r214145  
    7373}
    7474
     75// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasrestrictedglobalproperty
     76static bool hasRestrictedGlobalProperty(ExecState* exec, JSGlobalObject* globalObject, PropertyName propertyName)
     77{
     78    PropertyDescriptor descriptor;
     79    if (!globalObject->getOwnPropertyDescriptor(exec, propertyName, descriptor))
     80        return false;
     81    if (descriptor.configurable())
     82        return false;
     83    return true;
     84}
     85
    7586JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)
    7687{
     
    119130        // It's an error to introduce a shadow.
    120131        for (auto& entry : lexicalDeclarations) {
    121             bool hasProperty = globalObject->hasProperty(exec, entry.key.get());
    122             RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
    123             if (hasProperty) {
    124                 // The ES6 spec says that just RestrictedGlobalProperty can't be shadowed
    125                 // This carried out section 8.1.1.4.14 of the ES6 spec: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasrestrictedglobalproperty
    126                 PropertyDescriptor descriptor;
    127                 globalObject->getOwnPropertyDescriptor(exec, entry.key.get(), descriptor);
    128                
    129                 if (descriptor.value() != jsUndefined() && !descriptor.configurable())
    130                     return createSyntaxError(exec, makeString("Can't create duplicate variable that shadows a global property: '", String(entry.key.get()), "'"));
    131             }
    132 
    133             hasProperty = globalLexicalEnvironment->hasProperty(exec, entry.key.get());
     132            // The ES6 spec says that RestrictedGlobalProperty can't be shadowed.
     133            if (hasRestrictedGlobalProperty(exec, globalObject, entry.key.get()))
     134                return createSyntaxError(exec, makeString("Can't create duplicate variable that shadows a global property: '", String(entry.key.get()), "'"));
     135
     136            bool hasProperty = globalLexicalEnvironment->hasProperty(exec, entry.key.get());
    134137            RETURN_IF_EXCEPTION(throwScope, throwScope.exception());
    135138            if (hasProperty) {
Note: See TracChangeset for help on using the changeset viewer.