Skip to content
  • mhahnenberg@apple.com's avatar
    Change behavior of MasqueradesAsUndefined to better accommodate DFG changes · 3b9069ce
    mhahnenberg@apple.com authored
    https://bugs.webkit.org/show_bug.cgi?id=93884
    
    Reviewed by Filip Pizlo.
    
    Source/JavaScriptCore: 
    
    With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of  
    MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines,  
    we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined  
    objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject).  
    For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not  
    masquerade as undefined within frame B, but it will continue to masquerade in frame A. 
    
    There are two primary changes that are taking place here. One is to thread the ExecState* through  
    JSValue::toBoolean and JSCell::toBoolean so that JSCell::toBoolean can check the object's  
    JSGlobalObject to compare it to the lexical JSGlobalObject of the currently running code. If the two  
    are distinct, then the object cannot MasqueradeAsUndefined. 
    
    The other change is to perform this comparison of JSGlobalObjects everywhere where the MasqueradesAsUndefined 
    flag in the Structure is checked. For C++ code, this check has been factored into its own function in  
    Structure::masqueradesAsUndefined. We only perform this check in the DFG if the current JSGlobalObject has  
    had a MasqueradesAsUndefined object allocated within its context. This conditional compilation is managed  
    through the use of a WatchpointSet in each JSGlobalObject and alternate create() functions for JS DOM wrappers 
    that are MasqueradesAsUndefined.
    
    * API/JSValueRef.cpp:
    (JSValueToBoolean):
    * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
    * bytecode/Watchpoint.h:
    (WatchpointSet):
    * debugger/DebuggerCallFrame.h:
    (JSC::DebuggerCallFrame::callFrame):
    * dfg/DFGAbstractState.cpp:
    (JSC::DFG::AbstractState::execute):
    * dfg/DFGCFGSimplificationPhase.cpp:
    (JSC::DFG::CFGSimplificationPhase::run):
    * dfg/DFGOperations.cpp:
    * dfg/DFGOperations.h:
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
    (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
    (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
    (JSC::DFG::SpeculativeJIT::compile):
    * interpreter/Interpreter.cpp:
    (JSC::Interpreter::privateExecute):
    * jit/JITOpcodes.cpp:
    (JSC::JIT::emit_op_is_undefined):
    (JSC::JIT::emit_op_jeq_null):
    (JSC::JIT::emit_op_jneq_null):
    (JSC::JIT::emit_op_eq_null):
    (JSC::JIT::emit_op_neq_null):
    * jit/JITOpcodes32_64.cpp:
    (JSC::JIT::emit_op_is_undefined):
    (JSC::JIT::emit_op_jeq_null):
    (JSC::JIT::emit_op_jneq_null):
    (JSC::JIT::emit_op_eq_null):
    (JSC::JIT::emit_op_neq_null):
    * jit/JITStubs.cpp:
    (JSC::DEFINE_STUB_FUNCTION):
    * llint/LLIntSlowPaths.cpp:
    (JSC::LLInt::LLINT_SLOW_PATH_DECL):
    * llint/LowLevelInterpreter32_64.asm:
    * llint/LowLevelInterpreter64.asm:
    * runtime/ArrayPrototype.cpp:
    (JSC::arrayProtoFuncFilter):
    (JSC::arrayProtoFuncEvery):
    (JSC::arrayProtoFuncSome):
    * runtime/BooleanConstructor.cpp:
    (JSC::constructBoolean):
    (JSC::callBooleanConstructor):
    * runtime/JSCell.h:
    (JSCell):
    * runtime/JSGlobalObject.cpp:
    (JSC::JSGlobalObject::JSGlobalObject):
    * runtime/JSGlobalObject.h:
    (JSGlobalObject):
    (JSC::JSGlobalObject::masqueradesAsUndefinedWatchpoint):
    * runtime/JSString.h:
    (JSC::JSCell::toBoolean):
    (JSC::JSValue::toBoolean):
    * runtime/JSValue.h:
    * runtime/ObjectConstructor.cpp:
    (JSC::toPropertyDescriptor):
    * runtime/Operations.cpp:
    (JSC::jsTypeStringForValue):
    (JSC::jsIsObjectType):
    * runtime/Operations.h:
    (JSC):
    (JSC::JSValue::equalSlowCaseInline):
    * runtime/RegExpConstructor.cpp:
    (JSC::setRegExpConstructorMultiline):
    * runtime/RegExpPrototype.cpp:
    (JSC::regExpProtoFuncToString):
    * runtime/Structure.h:
    (Structure):
    (JSC::Structure::globalObjectOffset):
    (JSC::Structure::masqueradesAsUndefined):
    (JSC):
    
    Source/WebCore: 
    
    With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of  
    MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines,  
    we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined  
    objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject).  
    For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not  
    masquerade as undefined within frame B, but it will continue to masquerade in frame A. 
    
    Test: fast/js/document-all-between-frames.html
    
    All of the changes in WebCore are simply passing the additional ExecState argument to JSValue::toBoolean. 
    
    * bindings/js/JSCustomSQLStatementErrorCallback.cpp:
    (WebCore::JSSQLStatementErrorCallback::handleEvent):
    * bindings/js/JSDOMWindowCustom.cpp:
    (WebCore::JSDOMWindow::addEventListener):
    (WebCore::JSDOMWindow::removeEventListener):
    * bindings/js/JSDataViewCustom.cpp:
    (WebCore::getDataViewMember):
    * bindings/js/JSDeviceMotionEventCustom.cpp:
    (WebCore::JSDeviceMotionEvent::initDeviceMotionEvent):
    * bindings/js/JSDeviceOrientationEventCustom.cpp:
    (WebCore::JSDeviceOrientationEvent::initDeviceOrientationEvent):
    * bindings/js/JSDictionary.cpp:
    (WebCore::JSDictionary::convertValue):
    * bindings/js/JSHTMLCanvasElementCustom.cpp:
    (WebCore::JSHTMLCanvasElement::getContext):
    * bindings/js/JSInspectorFrontendHostCustom.cpp:
    (WebCore::populateContextMenuItems):
    * bindings/js/JSMessageEventCustom.cpp:
    (WebCore::handleInitMessageEvent):
    * bindings/js/JSWebGLRenderingContextCustom.cpp:
    (WebCore::dataFunctionMatrix):
    * bindings/js/JSXMLHttpRequestCustom.cpp:
    (WebCore::JSXMLHttpRequest::open):
    * bindings/js/JavaScriptCallFrame.cpp:
    (WebCore::JavaScriptCallFrame::exec):
    (WebCore):
    * bindings/js/JavaScriptCallFrame.h:
    (JavaScriptCallFrame):
    * bindings/js/ScriptDebugServer.cpp:
    (WebCore::ScriptDebugServer::hasBreakpoint):
    * bindings/js/SerializedScriptValue.cpp:
    (WebCore::CloneSerializer::dumpIfTerminal):
    * bindings/scripts/CodeGeneratorJS.pm: Also add the custom create function for MasqueradesAsUndefined JS DOM wrappers. 
    (GenerateEventListenerCall):
    (GenerateHeader):
    (JSValueToNative):
    * bindings/scripts/test/JS/JSTestEventTarget.cpp:
    (WebCore::jsTestEventTargetPrototypeFunctionAddEventListener):
    (WebCore::jsTestEventTargetPrototypeFunctionRemoveEventListener):
    * bindings/scripts/test/JS/JSTestEventTarget.h:
    (WebCore::JSTestEventTarget::create):
    * bindings/scripts/test/JS/JSTestObj.cpp:
    (WebCore::setJSTestObjCreate):
    (WebCore::setJSTestObjReflectedBooleanAttr):
    (WebCore::setJSTestObjReflectedCustomBooleanAttr):
    (WebCore::jsTestObjPrototypeFunctionAddEventListener):
    (WebCore::jsTestObjPrototypeFunctionRemoveEventListener):
    * bridge/c/c_utility.cpp:
    (JSC::Bindings::convertValueToNPVariant):
    * bridge/jni/jni_jsobject.mm:
    (JavaJSObject::convertValueToJObject):
    * bridge/qt/qt_runtime.cpp:
    (JSC::Bindings::convertValueToQVariant):
    
    Source/WebKit/mac: 
    
    With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of  
    MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines,  
    we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined  
    objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject).  
    For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not  
    masquerade as undefined within frame B, but it will continue to masquerade in frame A. 
    
    * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
    (WebKit::NetscapePluginInstanceProxy::addValueToArray): Passing ExecState to toBoolean call.
    
    Source/WebKit2: 
    
    With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of  
    MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines,  
    we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined  
    objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject).  
    For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not  
    masquerade as undefined within frame B, but it will continue to masquerade in frame A.
    
    * WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:
    (WebKit::NPRuntimeObjectMap::convertJSValueToNPVariant): Passing ExecState to toBoolean call.
    
    LayoutTests: 
    
    Added a test that uses a variety of ways of checking whether something is correctly 
    masquerading as undefined (or not) in a subframe.
    
    * fast/js/document-all-between-frames-expected.txt: Added.
    * fast/js/document-all-between-frames.html: Added.
    * fast/js/resources/document-all-between-frames-subframe.html: Added.
    * platform/chromium/TestExpectations: Chromium treats document.all differently, so skip our new test.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@126494 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    3b9069ce