Ignore:
Timestamp:
Jul 31, 2013, 12:03:05 PM (12 years ago)
Author:
[email protected]
Message:

Some cleanup in JSValue::get
https://bugs.webkit.org/show_bug.cgi?id=119343

Reviewed by Geoff Garen.

Source/JavaScriptCore:

JSValue::get is implemented to:

1) Check if the value is a cell – if not, synthesize a prototype to search,
2) call getOwnPropertySlot on the cell,
3) if this returns false, cast to JSObject to get the prototype, and walk the prototype chain.

By all rights this should crash when passed a string and accessing a property that does not exist, because
the string is a cell, getOwnPropertySlot should return false, and the cast to JSObject should be unsafe.
To work around this, JSString::getOwnPropertySlot actually implements 'get' functionality - searching the
prototype chain, and faking out a return value of undefined if no property is found.

This is a huge hazard, since fixing JSString::getOwnPropertySlot or calling getOwnPropertySlot on cells
from elsewhere would introduce bugs. Fortunately it is only ever called in this one place.

The fix here is to move getOwnPropertySlot onto JSObjecte and end this madness - cells don't have property
slots anyway.

Interesting changes are in JSCJSValueInlines.h, JSString.cpp - the rest is pretty much all JSCell -> JSObject.

Source/WebCore:

  • WebCore.exp.in:
  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateHeader):
(GenerateImplementation):
(GenerateConstructorDeclaration):
(GenerateConstructorHelperMethods):

  • bridge/objc/objc_runtime.h:
  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::ObjcFallbackObjectImp::getOwnPropertySlot):

  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::getOwnPropertySlot):
(JSC::RuntimeArray::getOwnPropertySlotByIndex):

  • bridge/runtime_array.h:
  • bridge/runtime_method.cpp:

(JSC::RuntimeMethod::getOwnPropertySlot):

  • bridge/runtime_method.h:
  • bridge/runtime_object.cpp:

(JSC::Bindings::RuntimeObject::getOwnPropertySlot):

  • bridge/runtime_object.h:
    • getOwnPropertySlot, JSCell -> JSObject

Source/WebKit2:

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::JSNPObject::getOwnPropertySlot):

  • WebProcess/Plugins/Netscape/JSNPObject.h:
    • getOwnPropertySlot, JSCell -> JSObject
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h

    r153229 r153532  
    628628inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
    629629{
    630     if (UNLIKELY(!isCell())) {
    631         JSObject* prototype = synthesizePrototype(exec);
    632         if (!prototype->getPropertySlot(exec, propertyName, slot))
    633             return jsUndefined();
     630    // If this is a primitive, we'll need to synthesize the prototype -
     631    // and if it's a string there are special properties to check first.
     632    JSObject* object;
     633    if (UNLIKELY(!isObject())) {
     634        if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
     635            return slot.getValue(exec, propertyName);
     636        object = synthesizePrototype(exec);
     637    } else
     638        object = asObject(asCell());
     639   
     640    if (object->getPropertySlot(exec, propertyName, slot))
    634641        return slot.getValue(exec, propertyName);
    635     }
    636     JSCell* cell = asCell();
    637     while (true) {
    638         if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
    639             return slot.getValue(exec, propertyName);
    640         JSValue prototype = asObject(cell)->prototype();
    641         if (!prototype.isObject())
    642             return jsUndefined();
    643         cell = asObject(prototype);
    644     }
     642    return jsUndefined();
    645643}
    646644
     
    653651inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
    654652{
    655     if (UNLIKELY(!isCell())) {
    656         JSObject* prototype = synthesizePrototype(exec);
    657         if (!prototype->getPropertySlot(exec, propertyName, slot))
    658             return jsUndefined();
     653    // If this is a primitive, we'll need to synthesize the prototype -
     654    // and if it's a string there are special properties to check first.
     655    JSObject* object;
     656    if (UNLIKELY(!isObject())) {
     657        if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
     658            return slot.getValue(exec, propertyName);
     659        object = synthesizePrototype(exec);
     660    } else
     661        object = asObject(asCell());
     662   
     663    if (object->getPropertySlot(exec, propertyName, slot))
    659664        return slot.getValue(exec, propertyName);
    660     }
    661     JSCell* cell = const_cast<JSCell*>(asCell());
    662     while (true) {
    663         if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot))
    664             return slot.getValue(exec, propertyName);
    665         JSValue prototype = asObject(cell)->prototype();
    666         if (!prototype.isObject())
    667             return jsUndefined();
    668         cell = prototype.asCell();
    669     }
     665    return jsUndefined();
    670666}
    671667
Note: See TracChangeset for help on using the changeset viewer.