Changeset 225845 in webkit


Ignore:
Timestamp:
Dec 13, 2017 9:29:21 AM (6 years ago)
Author:
sbarati@apple.com
Message:

Fix how JSFunction handles "caller" and "arguments" for functions that don't have those properties
https://bugs.webkit.org/show_bug.cgi?id=163579
<rdar://problem/35455798>

Reviewed by Mark Lam.

JSTests:

  • stress/caller-and-arguments-properties-for-functions-that-dont-have-them.js: Added.

(assert):
(test1):
(i.test1):
(i.test1.C):
(i.test1.async.foo):
(i.test1.foo):
(test2):

Source/JavaScriptCore:

Some functions in JavaScript do not have the "caller" and "arguments" properties.
For example, strict functions do not. When reading our code that dealt with these
types of functions, it was simply all wrong. We were doing weird things depending
on the method table hook. This patch fixes this by doing what we should've been
doing all along: when the JSFunction does not own the "caller"/"arguments" property,
it should defer to its base class implementation for the various method table hooks.

  • runtime/JSFunction.cpp:

(JSC::JSFunction::put):
(JSC::JSFunction::deleteProperty):
(JSC::JSFunction::defineOwnProperty):

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r225844 r225845  
     12017-12-13  Saam Barati  <sbarati@apple.com>
     2
     3        Fix how JSFunction handles "caller" and "arguments" for functions that don't have those properties
     4        https://bugs.webkit.org/show_bug.cgi?id=163579
     5        <rdar://problem/35455798>
     6
     7        Reviewed by Mark Lam.
     8
     9        * stress/caller-and-arguments-properties-for-functions-that-dont-have-them.js: Added.
     10        (assert):
     11        (test1):
     12        (i.test1):
     13        (i.test1.C):
     14        (i.test1.async.foo):
     15        (i.test1.foo):
     16        (test2):
     17
    1182017-12-13  Saam Barati  <sbarati@apple.com>
    219
  • trunk/Source/JavaScriptCore/ChangeLog

    r225844 r225845  
     12017-12-13  Saam Barati  <sbarati@apple.com>
     2
     3        Fix how JSFunction handles "caller" and "arguments" for functions that don't have those properties
     4        https://bugs.webkit.org/show_bug.cgi?id=163579
     5        <rdar://problem/35455798>
     6
     7        Reviewed by Mark Lam.
     8
     9        Some functions in JavaScript do not have the "caller" and "arguments" properties.
     10        For example, strict functions do not. When reading our code that dealt with these
     11        types of functions, it was simply all wrong. We were doing weird things depending
     12        on the method table hook. This patch fixes this by doing what we should've been
     13        doing all along: when the JSFunction does not own the "caller"/"arguments" property,
     14        it should defer to its base class implementation for the various method table hooks.
     15
     16        * runtime/JSFunction.cpp:
     17        (JSC::JSFunction::put):
     18        (JSC::JSFunction::deleteProperty):
     19        (JSC::JSFunction::defineOwnProperty):
     20
    1212017-12-13  Saam Barati  <sbarati@apple.com>
    222
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r225273 r225845  
    472472
    473473    if (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller) {
    474         slot.disableCaching();
    475474        if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
    476             // This will trigger the property to be reified, if this is not already the case!
    477             // FIXME: Investigate if the `hasProperty()` call is even needed, as in the `!hasCallerAndArgumentsProperties()` case,
    478             // these properties are not lazy and should not need to be reified. (https://bugs.webkit.org/show_bug.cgi?id=163579)
    479             bool okay = thisObject->hasProperty(exec, propertyName);
    480             RETURN_IF_EXCEPTION(scope, false);
    481             ASSERT_UNUSED(okay, okay);
    482475            scope.release();
    483476            return Base::put(thisObject, exec, propertyName, value, slot);
    484477        }
     478        slot.disableCaching();
    485479        return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
    486480    }
     
    502496        FunctionExecutable* executable = thisObject->jsExecutable();
    503497       
    504         if (propertyName == vm.propertyNames->caller || propertyName == vm.propertyNames->arguments)
    505             return !executable->hasCallerAndArgumentsProperties();
     498        if ((propertyName == vm.propertyNames->caller || propertyName == vm.propertyNames->arguments) && executable->hasCallerAndArgumentsProperties())
     499            return false;
    506500
    507501        if (propertyName == vm.propertyNames->prototype && !executable->isArrowFunction())
     
    540534    if (propertyName == vm.propertyNames->arguments) {
    541535        if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
    542             if (thisObject->jsExecutable()->isClass()) {
    543                 thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
    544                 scope.release();
    545                 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
    546             }
    547             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
    548             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
    549                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject(vm)->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
    550536            scope.release();
    551537            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
     
    554540    } else if (propertyName == vm.propertyNames->caller) {
    555541        if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
    556             if (thisObject->jsExecutable()->isClass()) {
    557                 thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
    558                 scope.release();
    559                 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
    560             }
    561             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
    562             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
    563                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject(vm)->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
    564542            scope.release();
    565543            return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
Note: See TracChangeset for help on using the changeset viewer.