Commit 41dbaab8 authored by weinig@apple.com's avatar weinig@apple.com

JavaScriptCore:

2008-04-04  Sam Weinig  <sam@webkit.org>

        Reviewed by Geoffrey Garen.

        First step in implementing the "split window"

        - Add a GlobalThisValue to ExecState which should be used 
          in places that used to implement the "use the global object
          as this if null" rule.
        - Factor out lookupGetter/lookupSetter into virtual methods 
          on JSObject so that they can be forwarded.
        - Make defineGetter/defineSetter virtual methods for the same
          reason.
        - Have PrototypeReflexiveFunction store the globalObject used
          to create it so that it can be used to get the correct thisObject
          for eval.

        * API/JSObjectRef.cpp:
        (JSObjectCallAsFunction):
        * JavaScriptCore.exp:
        * kjs/Activation.h:
        * kjs/ExecState.cpp:
        (KJS::ExecState::ExecState):
        (KJS::GlobalExecState::GlobalExecState):
        * kjs/ExecState.h:
        (KJS::ExecState::globalThisValue):
        * kjs/ExecStateInlines.h:
        (KJS::ExecState::ExecState):
        (KJS::FunctionExecState::FunctionExecState):
        * kjs/JSGlobalObject.cpp:
        (KJS::JSGlobalObject::reset):
        (KJS::JSGlobalObject::toGlobalObject):
        * kjs/JSGlobalObject.h:
        (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
        (KJS::JSGlobalObject::JSGlobalObject):
        * kjs/array_instance.cpp:
        (KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
        (KJS::compareWithCompareFunctionForQSort):
        * kjs/array_object.cpp:
        (KJS::arrayProtoFuncSort):
        (KJS::arrayProtoFuncFilter):
        (KJS::arrayProtoFuncMap):
        (KJS::arrayProtoFuncEvery):
        (KJS::arrayProtoFuncForEach):
        (KJS::arrayProtoFuncSome):
        * kjs/function.cpp:
        (KJS::FunctionImp::callAsFunction):
        (KJS::ActivationImp::toThisObject):
        (KJS::globalFuncEval):
        (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
        (KJS::PrototypeReflexiveFunction::mark):
        * kjs/function.h:
        (KJS::PrototypeReflexiveFunction::cachedGlobalObject):
        * kjs/function_object.cpp:
        (KJS::functionProtoFuncApply):
        (KJS::functionProtoFuncCall):
        * kjs/nodes.cpp:
        (KJS::ExpressionNode::resolveAndCall):
        (KJS::FunctionCallValueNode::evaluate):
        (KJS::LocalVarFunctionCallNode::inlineEvaluate):
        (KJS::ScopedVarFunctionCallNode::inlineEvaluate):
        (KJS::FunctionCallBracketNode::evaluate):
        (KJS::FunctionCallDotNode::inlineEvaluate):
        * kjs/object.cpp:
        (KJS::JSObject::call):
        (KJS::JSObject::put):
        (KJS::tryGetAndCallProperty):
        (KJS::JSObject::lookupGetter):
        (KJS::JSObject::lookupSetter):
        (KJS::JSObject::toThisObject):
        (KJS::JSObject::toGlobalObject):
        (KJS::JSObject::fillGetterPropertySlot):
        * kjs/object.h:
        * kjs/object_object.cpp:
        (KJS::objectProtoFuncLookupGetter):
        (KJS::objectProtoFuncLookupSetter):
        * kjs/string_object.cpp:
        (KJS::replace):

WebCore:

2008-04-04  Sam Weinig  <sam@webkit.org>

        Reviewed by Geoffrey Garen.

        First step in implementing the "split window"

        - This patch takes the first step in changing the window navigation model
          from clearing the window properties on navigation, to replacing
          an inner window.  This is necessary to safely perform security checks
          using the lexical global object.

          This first step adds a new class called JSDOMWindowWrapper, which wraps
          the real window object.  All JS calls that would go to the window object
          now go to it, which it forwards to the current inner window.  To accomplish
          this, the wrapper window is used as the ThisValue wherever the window was used
          before.

        * WebCore.base.exp:
        * WebCore.xcodeproj/project.pbxproj:
        * bindings/js/JSDOMWindowBase.cpp:
        (WebCore::JSDOMWindowBase::JSDOMWindowBase):
        (WebCore::JSDOMWindowBase::clear): Reset the wrapper windows prototype too.
        (WebCore::JSDOMWindowBase::toThisObject):
        (WebCore::JSDOMWindowBase::wrapper):
        (WebCore::windowProtoFuncAToB):
        (WebCore::windowProtoFuncBToA):
        (WebCore::windowProtoFuncOpen):
        (WebCore::windowProtoFuncSetTimeout):
        (WebCore::windowProtoFuncClearTimeout):
        (WebCore::windowProtoFuncSetInterval):
        (WebCore::windowProtoFuncAddEventListener):
        (WebCore::windowProtoFuncRemoveEventListener):
        (WebCore::windowProtoFuncShowModalDialog):
        (WebCore::windowProtoFuncNotImplemented):
        (WebCore::toJS):
        * bindings/js/JSDOMWindowBase.h:
        Fix to expect the wrapper as the thisObj.
        * bindings/js/JSDOMWindowCustom.cpp:
        (WebCore::JSDOMWindow::postMessage):
        (WebCore::toDOMWindow):
        * bindings/js/JSDOMWindowWrapper.cpp: Added.
        (WebCore::):
        (WebCore::JSDOMWindowWrapper::JSDOMWindowWrapper):
        (WebCore::JSDOMWindowWrapper::~JSDOMWindowWrapper):
        (WebCore::JSDOMWindowWrapper::mark):
        (WebCore::JSDOMWindowWrapper::className):
        (WebCore::JSDOMWindowWrapper::getOwnPropertySlot):
        (WebCore::JSDOMWindowWrapper::put):
        (WebCore::JSDOMWindowWrapper::deleteProperty):
        (WebCore::JSDOMWindowWrapper::getPropertyNames):
        (WebCore::JSDOMWindowWrapper::getPropertyAttributes):
        (WebCore::JSDOMWindowWrapper::defineGetter):
        (WebCore::JSDOMWindowWrapper::defineSetter):
        (WebCore::JSDOMWindowWrapper::lookupGetter):
        (WebCore::JSDOMWindowWrapper::lookupSetter):
        (WebCore::JSDOMWindowWrapper::toGlobalObject):
        (WebCore::JSDOMWindowWrapper::impl):
        (WebCore::JSDOMWindowWrapper::disconnectFrame):
        (WebCore::JSDOMWindowWrapper::clear):
        (WebCore::toJS):
        * bindings/js/JSDOMWindowWrapper.h: Added.
        (WebCore::JSDOMWindowWrapper::innerWindow):
        (WebCore::JSDOMWindowWrapper::setInnerWindow):
        (WebCore::JSDOMWindowWrapper::classInfo):
        Forward methods to the innerWindow.
        * bindings/js/JSHTMLDocumentCustom.cpp:
        (WebCore::JSHTMLDocument::open):
        * bindings/js/ScheduledAction.cpp:
        (WebCore::ScheduledAction::execute):
        * bindings/js/kjs_events.cpp:
        (WebCore::JSAbstractEventListener::handleEvent):
        * bindings/js/kjs_proxy.cpp:
        (WebCore::KJSProxy::~KJSProxy):
        (WebCore::KJSProxy::evaluate):
        (WebCore::KJSProxy::clear):
        (WebCore::KJSProxy::initScript):
        (WebCore::KJSProxy::clearDocumentWrapper):
        (WebCore::KJSProxy::processingUserGesture):
        (WebCore::KJSProxy::attachDebugger):
        * bindings/js/kjs_proxy.h:
        (WebCore::KJSProxy::haveWindowWrapper):
        (WebCore::KJSProxy::windowWrapper):
        (WebCore::KJSProxy::globalObject):
        (WebCore::KJSProxy::initScriptIfNeeded):
        Hold onto the wrapper window instead of global object.  As a convenience,
        keep the globalObject() as a forward to the inner window.
        * bindings/objc/DOMUtility.mm:
        (KJS::createDOMWrapper):
        * bindings/scripts/CodeGeneratorJS.pm:
        * dom/Document.cpp:
        (WebCore::Document::domWindow):
        * dom/Document.h:
        (WebCore::Document::defaultView):
        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::dispatchWindowObjectAvailable):
        * page/DOMWindow.idl:
        * page/Frame.cpp:
        (WebCore::Frame::~Frame):
        (WebCore::Frame::pageDestroyed):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31746 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 38797c1b
......@@ -286,8 +286,8 @@ JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObject
JSObject* jsThisObject = toJS(thisObject);
if (!jsThisObject)
jsThisObject = exec->dynamicGlobalObject();
jsThisObject = exec->globalThisValue();
List argList;
for (size_t i = 0; i < argumentCount; i++)
argList.append(toJS(arguments[i]));
......
2008-04-04 Sam Weinig <sam@webkit.org>
Reviewed by Geoffrey Garen.
First step in implementing the "split window"
- Add a GlobalThisValue to ExecState which should be used
in places that used to implement the "use the global object
as this if null" rule.
- Factor out lookupGetter/lookupSetter into virtual methods
on JSObject so that they can be forwarded.
- Make defineGetter/defineSetter virtual methods for the same
reason.
- Have PrototypeReflexiveFunction store the globalObject used
to create it so that it can be used to get the correct thisObject
for eval.
* API/JSObjectRef.cpp:
(JSObjectCallAsFunction):
* JavaScriptCore.exp:
* kjs/Activation.h:
* kjs/ExecState.cpp:
(KJS::ExecState::ExecState):
(KJS::GlobalExecState::GlobalExecState):
* kjs/ExecState.h:
(KJS::ExecState::globalThisValue):
* kjs/ExecStateInlines.h:
(KJS::ExecState::ExecState):
(KJS::FunctionExecState::FunctionExecState):
* kjs/JSGlobalObject.cpp:
(KJS::JSGlobalObject::reset):
(KJS::JSGlobalObject::toGlobalObject):
* kjs/JSGlobalObject.h:
(KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData):
(KJS::JSGlobalObject::JSGlobalObject):
* kjs/array_instance.cpp:
(KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
(KJS::compareWithCompareFunctionForQSort):
* kjs/array_object.cpp:
(KJS::arrayProtoFuncSort):
(KJS::arrayProtoFuncFilter):
(KJS::arrayProtoFuncMap):
(KJS::arrayProtoFuncEvery):
(KJS::arrayProtoFuncForEach):
(KJS::arrayProtoFuncSome):
* kjs/function.cpp:
(KJS::FunctionImp::callAsFunction):
(KJS::ActivationImp::toThisObject):
(KJS::globalFuncEval):
(KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction):
(KJS::PrototypeReflexiveFunction::mark):
* kjs/function.h:
(KJS::PrototypeReflexiveFunction::cachedGlobalObject):
* kjs/function_object.cpp:
(KJS::functionProtoFuncApply):
(KJS::functionProtoFuncCall):
* kjs/nodes.cpp:
(KJS::ExpressionNode::resolveAndCall):
(KJS::FunctionCallValueNode::evaluate):
(KJS::LocalVarFunctionCallNode::inlineEvaluate):
(KJS::ScopedVarFunctionCallNode::inlineEvaluate):
(KJS::FunctionCallBracketNode::evaluate):
(KJS::FunctionCallDotNode::inlineEvaluate):
* kjs/object.cpp:
(KJS::JSObject::call):
(KJS::JSObject::put):
(KJS::tryGetAndCallProperty):
(KJS::JSObject::lookupGetter):
(KJS::JSObject::lookupSetter):
(KJS::JSObject::toThisObject):
(KJS::JSObject::toGlobalObject):
(KJS::JSObject::fillGetterPropertySlot):
* kjs/object.h:
* kjs/object_object.cpp:
(KJS::objectProtoFuncLookupGetter):
(KJS::objectProtoFuncLookupSetter):
* kjs/string_object.cpp:
(KJS::replace):
2008-04-08 Brady Eidson <beidson@apple.com>
Encourage Windows to rebuild - AGAIN...
......
......@@ -121,7 +121,7 @@ __ZN3KJS14StringInstance3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueE
__ZN3KJS14StringInstance4infoE
__ZN3KJS14StringInstanceC1EPNS_8JSObjectERKNS_7UStringE
__ZN3KJS14StringInstanceC2EPNS_8JSObjectERKNS_7UStringE
__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectE
__ZN3KJS15GlobalExecStateC1EPNS_14JSGlobalObjectEPNS_8JSObjectE
__ZN3KJS15JSWrapperObject4markEv
__ZN3KJS15SavedPropertiesC1Ev
__ZN3KJS15SavedPropertiesD1Ev
......@@ -168,6 +168,10 @@ __ZN3KJS8Debugger9exceptionEPNS_9ExecStateEiiPNS_7JSValueE
__ZN3KJS8DebuggerC2Ev
__ZN3KJS8DebuggerD2Ev
__ZN3KJS8JSObject11hasInstanceEPNS_9ExecStateEPNS_7JSValueE
__ZN3KJS8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3KJS8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
__ZN3KJS8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
__ZN3KJS8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
__ZN3KJS8JSObject12removeDirectERKNS_10IdentifierE
__ZN3KJS8JSObject14callAsFunctionEPNS_9ExecStateEPS0_RKNS_4ListE
__ZN3KJS8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
......@@ -230,6 +234,7 @@ __ZNK3KJS12DateInstance7getTimeERdRi
__ZNK3KJS13ArrayInstance7getItemEj
__ZNK3KJS14JSGlobalObject12saveBuiltinsERNS_13SavedBuiltinsE
__ZNK3KJS14JSGlobalObject14isDynamicScopeEv
__ZNK3KJS14JSGlobalObject14toGlobalObjectEPNS_9ExecStateE
__ZNK3KJS16JSVariableObject16isVariableObjectEv
__ZNK3KJS16JSVariableObject16saveLocalStorageERNS_15SavedPropertiesE
__ZNK3KJS16JSVariableObject21getPropertyAttributesERKNS_10IdentifierERj
......@@ -257,7 +262,9 @@ __ZNK3KJS7UString8toUInt32EPbb
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
__ZNK3KJS8JSObject11hasPropertyEPNS_9ExecStateEj
__ZNK3KJS8JSObject12defaultValueEPNS_9ExecStateENS_6JSTypeE
__ZNK3KJS8JSObject12toThisObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject14implementsCallEv
__ZNK3KJS8JSObject14toGlobalObjectEPNS_9ExecStateE
__ZNK3KJS8JSObject19implementsConstructEv
__ZNK3KJS8JSObject21getPropertyAttributesERKNS_10IdentifierERj
__ZNK3KJS8JSObject21implementsHasInstanceEv
......
......@@ -66,6 +66,8 @@ namespace KJS {
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
virtual JSObject* toThisObject(ExecState*) const;
virtual void mark();
void markChildren();
......
......@@ -42,7 +42,7 @@ static inline List* globalEmptyList()
// ECMA 10.2
// The constructor for the globalExec pseudo-ExecState
inline ExecState::ExecState(JSGlobalObject* globalObject)
inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject)
: m_globalObject(globalObject)
, m_exception(0)
, m_propertyNames(CommonIdentifiers::shared())
......@@ -55,7 +55,8 @@ inline ExecState::ExecState(JSGlobalObject* globalObject)
, m_localStorage(&globalObject->localStorage())
, m_inlineScopeChainNode(0, 0)
, m_variableObject(globalObject)
, m_thisValue(globalObject)
, m_thisValue(thisObject)
, m_globalThisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(GlobalCode)
......@@ -77,6 +78,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
, m_inlineScopeChainNode(0, 0)
, m_variableObject(globalObject)
, m_thisValue(thisObject)
, m_globalThisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(GlobalCode)
......@@ -100,6 +102,7 @@ inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
, m_inlineScopeChainNode(0, 0)
, m_variableObject(variableObject)
, m_thisValue(thisObject)
, m_globalThisValue(thisObject)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(EvalCode)
......@@ -115,8 +118,8 @@ JSGlobalObject* ExecState::lexicalGlobalObject() const
return m_globalObject;
}
GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
: ExecState(globalObject)
GlobalExecState::GlobalExecState(JSGlobalObject* globalObject, JSObject* thisObject)
: ExecState(globalObject, thisObject)
{
}
......
......@@ -73,6 +73,7 @@ namespace KJS {
void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
JSObject* thisValue() const { return m_thisValue; }
JSObject* globalThisValue() const { return m_globalThisValue; }
ExecState* callingExecState() { return m_callingExec; }
......@@ -164,10 +165,10 @@ namespace KJS {
}
protected:
ExecState(JSGlobalObject*);
ExecState(JSGlobalObject*, JSObject* thisObject);
ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
ExecState(JSGlobalObject*, JSObject* thisObject, EvalNode*, ExecState* callingExecState, const ScopeChain&, JSVariableObject*);
ExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*, ExecState* callingExecState, FunctionImp*, const List& args);
ExecState(JSGlobalObject*, JSObject* thisObject, JSObject* globalThisValue, FunctionBodyNode*, ExecState* callingExecState, FunctionImp*, const List& args);
~ExecState();
// ExecStates are always stack-allocated, and the garbage collector
......@@ -190,7 +191,9 @@ namespace KJS {
ScopeChain m_scopeChain;
ScopeChainNode m_inlineScopeChainNode;
JSVariableObject* m_variableObject;
JSObject* m_thisValue;
JSObject* m_globalThisValue;
LabelStack m_labelStack;
int m_iterationDepth;
......@@ -203,7 +206,7 @@ namespace KJS {
class GlobalExecState : public ExecState {
public:
GlobalExecState(JSGlobalObject*);
GlobalExecState(JSGlobalObject*, JSObject* thisObject);
~GlobalExecState();
};
......@@ -221,7 +224,7 @@ namespace KJS {
class FunctionExecState : public ExecState {
public:
FunctionExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*,
FunctionExecState(JSGlobalObject*, JSObject* thisObject, JSObject* globalThisValue, FunctionBodyNode*,
ExecState* callingExecState, FunctionImp*, const List& args);
~FunctionExecState();
};
......
......@@ -30,7 +30,7 @@
namespace KJS {
inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, JSObject* globalThisValue,
FunctionBodyNode* functionBodyNode, ExecState* callingExec,
FunctionImp* func, const List& args)
: m_globalObject(globalObject)
......@@ -44,6 +44,7 @@ namespace KJS {
, m_scopeChain(func->scope())
, m_inlineScopeChainNode(0, 0)
, m_thisValue(thisObject)
, m_globalThisValue(globalThisValue)
, m_iterationDepth(0)
, m_switchDepth(0)
, m_codeType(FunctionCode)
......@@ -68,10 +69,10 @@ namespace KJS {
{
}
inline FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject,
inline FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject, JSObject* globalThisValue,
FunctionBodyNode* functionBodyNode, ExecState* callingExec,
FunctionImp* func, const List& args)
: ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
: ExecState(globalObject, thisObject, globalThisValue, functionBodyNode, callingExec, func, args)
{
m_globalObject->activeExecStates().append(this);
}
......
......@@ -327,7 +327,7 @@ void JSGlobalObject::reset(JSValue* prototype)
// Set global functions.
d()->evalFunction = new PrototypeReflexiveFunction(exec, d()->functionPrototype, 1, exec->propertyNames().eval, globalFuncEval);
d()->evalFunction = new PrototypeReflexiveFunction(exec, d()->functionPrototype, 1, exec->propertyNames().eval, globalFuncEval, this);
putDirectFunction(d()->evalFunction, DontEnum);
putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 2, "parseInt", globalFuncParseInt), DontEnum);
putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "parseFloat", globalFuncParseFloat), DontEnum);
......@@ -534,6 +534,11 @@ void JSGlobalObject::mark()
markIfNeeded(d()->URIErrorPrototype);
}
JSGlobalObject* JSGlobalObject::toGlobalObject(ExecState*) const
{
return const_cast<JSGlobalObject*>(this);
}
ExecState* JSGlobalObject::globalExec()
{
return &d()->globalExec;
......
......@@ -76,9 +76,9 @@ namespace KJS {
using JSVariableObject::JSVariableObjectData;
struct JSGlobalObjectData : public JSVariableObjectData {
JSGlobalObjectData(JSGlobalObject* globalObject)
JSGlobalObjectData(JSGlobalObject* globalObject, JSObject* thisValue)
: JSVariableObjectData(&inlineSymbolTable)
, globalExec(globalObject)
, globalExec(globalObject, thisValue)
{
}
......@@ -141,14 +141,14 @@ namespace KJS {
public:
JSGlobalObject()
: JSVariableObject(new JSGlobalObjectData(this))
: JSVariableObject(new JSGlobalObjectData(this, this))
{
init();
}
protected:
JSGlobalObject(JSValue* proto)
: JSVariableObject(proto, new JSGlobalObjectData(this))
JSGlobalObject(JSValue* proto, JSObject* globalThisValue)
: JSVariableObject(proto, new JSGlobalObjectData(this, globalThisValue))
{
init();
}
......@@ -225,6 +225,7 @@ namespace KJS {
virtual void mark();
virtual bool isGlobalObject() const { return true; }
virtual JSGlobalObject* toGlobalObject(ExecState*) const;
virtual ExecState* globalExec();
......
......@@ -23,7 +23,6 @@
#include "config.h"
#include "array_instance.h"
#include "JSGlobalObject.h"
#include "PropertyNameArray.h"
#include <wtf/Assertions.h>
......@@ -489,14 +488,14 @@ struct CompareWithCompareFunctionArguments {
CompareWithCompareFunctionArguments(ExecState *e, JSObject *cf)
: exec(e)
, compareFunction(cf)
, globalObject(e->dynamicGlobalObject())
, globalThisValue(e->globalThisValue())
{
}
ExecState *exec;
JSObject *compareFunction;
List arguments;
JSGlobalObject* globalObject;
JSObject* globalThisValue;
};
static CompareWithCompareFunctionArguments* compareWithCompareFunctionArguments = 0;
......@@ -513,8 +512,7 @@ static int compareWithCompareFunctionForQSort(const void* a, const void* b)
args->arguments.clear();
args->arguments.append(va);
args->arguments.append(vb);
double compareResult = args->compareFunction->call
(args->exec, args->globalObject, args->arguments)->toNumber(args->exec);
double compareResult = args->compareFunction->call(args->exec, args->globalThisValue, args->arguments)->toNumber(args->exec);
return compareResult < 0 ? -1 : compareResult > 0 ? 1 : 0;
}
......
......@@ -404,7 +404,7 @@ JSValue* arrayProtoFuncSort(ExecState* exec, JSObject* thisObj, const List& args
List l;
l.append(jObj);
l.append(minObj);
compareResult = sortFunction->call(exec, exec->dynamicGlobalObject(), l)->toNumber(exec);
compareResult = sortFunction->call(exec, exec->globalThisValue(), l)->toNumber(exec);
} else
compareResult = (jObj->toString(exec) < minObj->toString(exec)) ? -1 : 1;
......@@ -502,7 +502,7 @@ JSValue* arrayProtoFuncFilter(ExecState* exec, JSObject* thisObj, const List& ar
if (!eachFunction->implementsCall())
return throwError(exec, TypeError);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);
JSObject* resultArray = static_cast<JSObject*>(exec->lexicalGlobalObject()->arrayConstructor()->construct(exec, exec->emptyList()));
unsigned filterIndex = 0;
......@@ -535,7 +535,7 @@ JSValue* arrayProtoFuncMap(ExecState* exec, JSObject* thisObj, const List& args)
if (!eachFunction->implementsCall())
return throwError(exec, TypeError);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
......@@ -575,7 +575,7 @@ JSValue* arrayProtoFuncEvery(ExecState* exec, JSObject* thisObj, const List& arg
if (!eachFunction->implementsCall())
return throwError(exec, TypeError);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);
JSValue* result = jsBoolean(true);
......@@ -610,7 +610,7 @@ JSValue* arrayProtoFuncForEach(ExecState* exec, JSObject* thisObj, const List& a
if (!eachFunction->implementsCall())
return throwError(exec, TypeError);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);
unsigned length = thisObj->get(exec, exec->propertyNames().length)->toUInt32(exec);
for (unsigned k = 0; k < length && !exec->hadException(); ++k) {
......@@ -635,7 +635,7 @@ JSValue* arrayProtoFuncSome(ExecState* exec, JSObject* thisObj, const List& args
if (!eachFunction->implementsCall())
return throwError(exec, TypeError);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->dynamicGlobalObject() : args[1]->toObject(exec);
JSObject* applyThis = args[1]->isUndefinedOrNull() ? exec->globalThisValue() : args[1]->toObject(exec);
JSValue* result = jsBoolean(false);
......
......@@ -73,7 +73,7 @@ void FunctionImp::mark()
JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
{
FunctionExecState newExec(exec->dynamicGlobalObject(), thisObj, body.get(), exec, this, args);
FunctionExecState newExec(exec->dynamicGlobalObject(), thisObj, exec->globalThisValue(), body.get(), exec, this, args);
JSValue* result = body->execute(&newExec);
if (newExec.completionType() == ReturnValue)
return result;
......@@ -466,6 +466,11 @@ void ActivationImp::createArgumentsObject(ExecState* exec)
d()->argumentsObject = new Arguments(exec, d()->exec->function(), *d()->exec->arguments(), this);
}
JSObject* ActivationImp::toThisObject(ExecState* exec) const
{
return exec->globalThisValue();
}
ActivationImp::ActivationData::ActivationData(const ActivationData& old)
: JSVariableObjectData(old)
, exec(old.exec)
......@@ -738,13 +743,13 @@ JSValue* eval(ExecState* exec, const ScopeChain& scopeChain, JSVariableObject* v
JSValue* globalFuncEval(ExecState* exec, PrototypeReflexiveFunction* function, JSObject* thisObj, const List& args)
{
JSGlobalObject* globalObject = thisObj->isGlobalObject() ? static_cast<JSGlobalObject*>(thisObj) : 0;
JSGlobalObject* globalObject = thisObj->toGlobalObject(exec);
if (!globalObject || globalObject->evalFunction() != function)
return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
ScopeChain scopeChain(globalObject);
return eval(exec, scopeChain, globalObject, globalObject, globalObject, args);
return eval(exec, scopeChain, globalObject, globalObject, function->cachedGlobalObject()->toThisObject(exec), args);
}
JSValue* globalFuncParseInt(ExecState* exec, JSObject*, const List& args)
......@@ -890,11 +895,13 @@ JSValue* PrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, c
// ------------------------------ PrototypeReflexiveFunction -------------------------------
PrototypeReflexiveFunction::PrototypeReflexiveFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, JSMemberFunction function)
PrototypeReflexiveFunction::PrototypeReflexiveFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, JSMemberFunction function, JSGlobalObject* cachedGlobalObject)
: InternalFunctionImp(functionPrototype, name)
, m_function(function)
, m_cachedGlobalObject(cachedGlobalObject)
{
ASSERT_ARG(function, function);
ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
putDirect(exec->propertyNames().length, jsNumber(len), DontDelete | ReadOnly | DontEnum);
}
......@@ -903,4 +910,11 @@ JSValue* PrototypeReflexiveFunction::callAsFunction(ExecState* exec, JSObject* t
return m_function(exec, this, thisObj, args);
}
void PrototypeReflexiveFunction::mark()
{
InternalFunctionImp::mark();
if (!m_cachedGlobalObject->marked())
m_cachedGlobalObject->mark();
}
} // namespace KJS
......@@ -142,12 +142,16 @@ namespace KJS {
public:
typedef JSValue* (*JSMemberFunction)(ExecState*, PrototypeReflexiveFunction*, JSObject* thisObj, const List&);
PrototypeReflexiveFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, JSMemberFunction);
PrototypeReflexiveFunction(ExecState*, FunctionPrototype*, int len, const Identifier&, JSMemberFunction, JSGlobalObject* expectedThisObject);
virtual void mark();
virtual JSValue* callAsFunction(ExecState* exec, JSObject* thisObj, const List&);
JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
private:
const JSMemberFunction m_function;
JSGlobalObject* m_cachedGlobalObject;
};
// Global Functions
......
......@@ -86,7 +86,7 @@ JSValue* functionProtoFuncApply(ExecState* exec, JSObject* thisObj, const List&
JSObject* applyThis;
if (thisArg->isUndefinedOrNull())
applyThis = exec->dynamicGlobalObject();
applyThis = exec->globalThisValue();
else
applyThis = thisArg->toObject(exec);
......@@ -116,7 +116,7 @@ JSValue* functionProtoFuncCall(ExecState* exec, JSObject* thisObj, const List& a
JSObject* callThis;
if (thisArg->isUndefinedOrNull())
callThis = exec->dynamicGlobalObject();
callThis = exec->globalThisValue();
else
callThis = thisArg->toObject(exec);
......
......@@ -1122,22 +1122,14 @@ inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier
args->evaluateList(exec, argList);
KJS_CHECKEXCEPTIONVALUE
JSObject* thisObj = base;
// ECMA 11.2.3 says that in this situation the this value should be null.
// However, section 10.2.3 says that in the case where the value provided
// by the caller is null, the global object should be used. It also says
// that the section does not apply to internal functions, but for simplicity
// of implementation we use the global object anyway here. This guarantees
// that in host objects you always get a valid object for this.
if (thisObj->isActivationObject())
thisObj = exec->dynamicGlobalObject();
if (callerType == EvalOperator) {
if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
exec->dynamicGlobalObject()->tearOffActivation(exec);
return eval(exec, exec->scopeChain(), exec->variableObject(), exec->dynamicGlobalObject(), exec->thisValue(), argList);
}
}
JSObject* thisObj = base->toThisObject(exec);
return func->call(exec, thisObj, argList);
}
++iter;
......@@ -1182,8 +1174,7 @@ JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
m_args->evaluateList(exec, argList);
KJS_CHECKEXCEPTIONVALUE
JSObject* thisObj = exec->dynamicGlobalObject();
JSObject* thisObj = exec->globalThisValue();
return func->call(exec, thisObj, argList);
}
......@@ -1266,7 +1257,8 @@ JSValue* LocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
m_args->evaluateList(exec, argList);
KJS_CHECKEXCEPTIONVALUE
return func->call(exec, exec->dynamicGlobalObject(), argList);
JSObject* thisObj = exec->globalThisValue();
return func->call(exec, thisObj, argList);
}
JSValue* LocalVarFunctionCallNode::evaluate(ExecState* exec)
......@@ -1318,8 +1310,9 @@ JSValue* ScopedVarFunctionCallNode::inlineEvaluate(ExecState* exec)
List argList;
m_args->evaluateList(exec, argList);
KJS_CHECKEXCEPTIONVALUE
return func->call(exec, exec->dynamicGlobalObject(), argList);
JSObject* thisObj = exec->globalThisValue();
return func->call(exec, thisObj, argList);
}
JSValue* ScopedVarFunctionCallNode::evaluate(ExecState* exec)
......@@ -1448,6 +1441,7 @@ JSValue* FunctionCallBracketNode::evaluate(ExecState* exec)
ASSERT(thisObj->isObject());
ASSERT(!thisObj->isActivationObject());
// No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
return func->call(exec, thisObj, argList);
}
......@@ -1497,6 +1491,7 @@ JSValue* FunctionCallDotNode::inlineEvaluate(ExecState* exec)
ASSERT(thisObj->isObject());
ASSERT(!thisObj->isActivationObject());
// No need to call toThisObject() on the thisObj as it is known not to be the GlobalObject or ActivationObject
return func->call(exec, thisObj, argList);
}
......
......@@ -93,7 +93,7 @@ JSValue *JSObject::call(ExecState *exec, JSObject *thisObj, const List &args)
}
#endif
JSValue *ret = callAsFunction(exec,thisObj,args);
JSValue* ret = callAsFunction(exec, thisObj, args);
#if KJS_MAX_STACK > 0
--depth;
......@@ -261,7 +261,7 @@ void JSObject::put(ExecState* exec, const Identifier &propertyName, JSValue *val
List args;
args.append(value);
setterFunc->call(exec, this, args);
setterFunc->call(exec, this->toThisObject(exec), args);
return;
} else {
// If there's an existing property on the object or one of its
......@@ -337,7 +337,7 @@ static ALWAYS_INLINE JSValue *tryGetAndCallProperty(ExecState *exec, const JSObj
JSObject *o = static_cast<JSObject*>(v);
if (o->implementsCall()) { // spec says "not primitive type" but ...
JSObject *thisObj = const_cast<JSObject*>(object);
JSValue* def = o->call(exec, thisObj, exec->emptyList());
JSValue* def = o->call(exec, thisObj->toThisObject(exec), exec->emptyList());
JSType defType = def->type();
ASSERT(defType != GetterSetterType);
if (defType != ObjectType)
......@@ -419,6 +419,46 @@ void JSObject::defineSetter(ExecState*, const Identifier& propertyName, JSObject
gs->setSetter(setterFunc);
}
JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
{