+2004-04-09 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by John.
+
+ Changed things so that newly created objects get a prototype based
+ on the scope chain of the current function, rather than the
+ interpreter that started execution. This fixes the following bugs:
+
+ <rdar://problem/3368523>: ARCH: wrong prototype used to create new objects (hang on lookup.atomica.com)
+ <rdar://problem/3559173>: ARCH: Cannot scan using a HP Jetdirect product (JS object prototypes bind incorrectly)
+
+ * JavaScriptCore.pbproj/project.pbxproj:
+ * kjs/array_object.cpp:
+ (CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments):
+ (ArrayProtoFuncImp::ArrayProtoFuncImp):
+ (ArrayProtoFuncImp::call):
+ (ArrayObjectImp::construct):
+ * kjs/bool_object.cpp:
+ (BooleanObjectImp::construct):
+ * kjs/date_object.cpp:
+ (DateProtoFuncImp::DateProtoFuncImp):
+ (DateProtoFuncImp::call):
+ (DateObjectImp::construct):
+ * kjs/error_object.cpp:
+ (ErrorObjectImp::construct):
+ * kjs/function.cpp:
+ (FunctionImp::FunctionImp):
+ (FunctionImp::call):
+ (DeclaredFunctionImp::construct):
+ (ArgumentsImp::ArgumentsImp):
+ (GlobalFuncImp::call):
+ * kjs/function_object.cpp:
+ (FunctionProtoFuncImp::call):
+ (FunctionObjectImp::construct):
+ * kjs/internal.cpp:
+ (BooleanImp::toObject):
+ (StringImp::toObject):
+ (NumberImp::toObject):
+ (InterpreterImp::InterpreterImp):
+ (InterpreterImp::clear):
+ (InterpreterImp::interpreterWithGlobalObject):
+ * kjs/internal.h:
+ * kjs/interpreter.cpp:
+ (ExecState::lexicalInterpreter):
+ * kjs/interpreter.h:
+ (KJS::ExecState::dynamicInterpreter):
+ (KJS::ExecState::interpreter):
+ * kjs/math_object.cpp:
+ (MathFuncImp::MathFuncImp):
+ * kjs/nodes.cpp:
+ (StatementNode::hitStatement):
+ (StatementNode::abortStatement):
+ (RegExpNode::evaluate):
+ (ElementNode::evaluate):
+ (ArrayNode::evaluate):
+ (ObjectLiteralNode::evaluate):
+ (PropertyValueNode::evaluate):
+ (FunctionCallNode::evaluate):
+ (FuncDeclNode::processFuncDecl):
+ (FuncExprNode::evaluate):
+ * kjs/number_object.cpp:
+ (NumberObjectImp::construct):
+ * kjs/object.cpp:
+ (KJS::ObjectImp::defaultValue):
+ (KJS::Error::create):
+ * kjs/object_object.cpp:
+ (ObjectObjectImp::construct):
+ * kjs/reference.cpp:
+ (Reference::putValue):
+ * kjs/regexp_object.cpp:
+ (RegExpProtoFuncImp::call):
+ (RegExpObjectImp::arrayOfMatches):
+ (RegExpObjectImp::construct):
+ * kjs/scope_chain.cpp:
+ (KJS::ScopeChain::bottom):
+ * kjs/scope_chain.h:
+ * kjs/string_object.cpp:
+ (StringProtoFuncImp::StringProtoFuncImp):
+ (StringProtoFuncImp::call):
+ (StringObjectImp::construct):
+
=== Safari-136 ===
=== Safari-135 ===
517BE7F50610E39600221947,
5199B1C0061B65BC0070C006,
5199B266061BB1300070C006,
+ 65AB004B06261CBA0076DE63,
);
isa = PBXHeadersBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
5182A4FC06010F8200CBD2F2,
5182A53C06012C3000CBD2F2,
5199B1BF061B65BC0070C006,
+ 65AB004A06261CBA0076DE63,
);
isa = PBXSourcesBuildPhase;
runOnlyForDeploymentPostprocessing = 0;
08FB77AEFE84172EC02AAC07 = {
children = (
938772E5038BFE19008635CE,
+ 65AB004806261CBA0076DE63,
+ 65AB004906261CBA0076DE63,
F692A84E0255597D01FF60F7,
F692A84D0255597D01FF60F7,
F692A84F0255597D01FF60F7,
settings = {
};
};
+ 65AB004806261CBA0076DE63 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ path = interpreter_map.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 65AB004906261CBA0076DE63 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ path = interpreter_map.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ 65AB004A06261CBA0076DE63 = {
+ fileRef = 65AB004806261CBA0076DE63;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ 65AB004B06261CBA0076DE63 = {
+ fileRef = 65AB004906261CBA0076DE63;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
//650
//651
//652
CompareWithCompareFunctionArguments(ExecState *e, ObjectImp *cf)
: exec(e)
, compareFunction(cf)
- , globalObject(e->interpreter()->globalObject())
+ , globalObject(e->dynamicInterpreter()->globalObject())
{
arguments.append(Undefined());
arguments.append(Undefined());
ArrayProtoFuncImp::ArrayProtoFuncImp(ExecState *exec, int i, int len)
: InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
), id(i)
{
Value protect(this);
break;
}
case Concat: {
- Object arr = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
+ Object arr = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));
int n = 0;
Value curArg = thisObj;
Object curObj = Object::dynamicCast(thisObj);
// http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
// We return a new array
- Object resObj = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
+ Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));
result = resObj;
double begin = args[0].toInteger(exec);
if (begin < 0) {
List l;
l.append(jObj);
l.append(minObj);
- cmp = sortFunction.call(exec, exec->interpreter()->globalObject(), l).toNumber(exec);
+ cmp = sortFunction.call(exec, exec->dynamicInterpreter()->globalObject(), l).toNumber(exec);
} else {
cmp = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1;
}
}
case Splice: {
// 15.4.4.12 - oh boy this is huge
- Object resObj = Object::dynamicCast(exec->interpreter()->builtinArray().construct(exec,List::empty()));
+ Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()));
result = resObj;
int begin = args[0].toUInt32(exec);
if ( begin < 0 )
exec->setException(error);
return error;
}
- return Object(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype().imp(), n));
+ return Object(new ArrayInstanceImp(exec->lexicalInterpreter()->builtinArrayPrototype().imp(), n));
}
// otherwise the array is constructed with the arguments in it
- return Object(new ArrayInstanceImp(exec->interpreter()->builtinArrayPrototype().imp(), args));
+ return Object(new ArrayInstanceImp(exec->lexicalInterpreter()->builtinArrayPrototype().imp(), args));
}
bool ArrayObjectImp::implementsCall() const
// ECMA 15.6.2
Object BooleanObjectImp::construct(ExecState *exec, const List &args)
{
- Object obj(new BooleanInstanceImp(exec->interpreter()->builtinBooleanPrototype().imp()));
+ Object obj(new BooleanInstanceImp(exec->lexicalInterpreter()->builtinBooleanPrototype().imp()));
Boolean b;
if (args.size() > 0)
DateProtoFuncImp::DateProtoFuncImp(ExecState *exec, int i, int len)
: InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
), id(abs(i)), utc(i<0)
// We use a negative ID to denote the "UTC" variant.
{
break;
case GetYear:
// IE returns the full year even in getYear.
- if ( exec->interpreter()->compatMode() == Interpreter::IECompat )
+ if ( exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat )
result = Number(1900 + t->tm_year);
else
result = Number(t->tm_year);
}
}
- Object proto = exec->interpreter()->builtinDatePrototype();
+ Object proto = exec->lexicalInterpreter()->builtinDatePrototype();
Object ret(new DateInstanceImp(proto.imp()));
ret.setInternalValue(timeClip(value));
return ret;
// ECMA 15.9.3
Object ErrorObjectImp::construct(ExecState *exec, const List &args)
{
- Object proto = Object::dynamicCast(exec->interpreter()->builtinErrorPrototype());
+ Object proto = Object::dynamicCast(exec->lexicalInterpreter()->builtinErrorPrototype());
ObjectImp *imp = new ObjectImp(proto);
Object obj(imp);
FunctionImp::FunctionImp(ExecState *exec, const Identifier &n)
: InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
), param(0L), ident(n)
{
}
Value FunctionImp::call(ExecState *exec, Object &thisObj, const List &args)
{
- Object &globalObj = exec->interpreter()->globalObject();
+ Object &globalObj = exec->dynamicInterpreter()->globalObject();
- Debugger *dbg = exec->interpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
int sid = -1;
int lineno = -1;
if (dbg) {
}
// enter a new execution context
- ContextImp ctx(globalObj, exec->interpreter()->imp(), thisObj, codeType(),
+ ContextImp ctx(globalObj, exec->dynamicInterpreter()->imp(), thisObj, codeType(),
exec->context().imp(), this, &args);
- ExecState newExec(exec->interpreter(), &ctx);
+ ExecState newExec(exec->dynamicInterpreter(), &ctx);
newExec.setException(exec->exception()); // could be null
// assign user supplied arguments to parameters
if (p.type() == ObjectType)
proto = Object(static_cast<ObjectImp*>(p.imp()));
else
- proto = exec->interpreter()->builtinObjectPrototype();
+ proto = exec->lexicalInterpreter()->builtinObjectPrototype();
Object obj(new ObjectImp(proto));
// ECMA 10.1.8
ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func)
- : ArrayInstanceImp(exec->interpreter()->builtinObjectPrototype().imp(), 0)
+ : ArrayInstanceImp(exec->lexicalInterpreter()->builtinObjectPrototype().imp(), 0)
{
Value protect(this);
putDirect(calleePropertyName, func, DontEnum);
}
ArgumentsImp::ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args)
- : ArrayInstanceImp(exec->interpreter()->builtinObjectPrototype().imp(), args)
+ : ArrayInstanceImp(exec->lexicalInterpreter()->builtinObjectPrototype().imp(), args)
{
Value protect(this);
putDirect(calleePropertyName, func, DontEnum);
// enter a new execution context
Object thisVal(Object::dynamicCast(exec->context().thisValue()));
- ContextImp ctx(exec->interpreter()->globalObject(),
- exec->interpreter()->imp(),
+ ContextImp ctx(exec->dynamicInterpreter()->globalObject(),
+ exec->dynamicInterpreter()->imp(),
thisVal,
EvalCode,
exec->context().imp());
- ExecState newExec(exec->interpreter(), &ctx);
+ ExecState newExec(exec->dynamicInterpreter(), &ctx);
newExec.setException(exec->exception()); // could be null
// execute the code
Object applyThis;
if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
- applyThis = exec->interpreter()->globalObject();
+ applyThis = exec->dynamicInterpreter()->globalObject();
else
applyThis = thisArg.toObject(exec);
Object callThis;
if (thisArg.isA(NullType) || thisArg.isA(UndefinedType))
- callThis = exec->interpreter()->globalObject();
+ callThis = exec->dynamicInterpreter()->globalObject();
else
callThis = thisArg.toObject(exec);
ProgramNode *progNode = Parser::parse(body.data(),body.size(),&sid,&errLine,&errMsg);
// notify debugger that source has been parsed
- Debugger *dbg = exec->interpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
if (dbg) {
bool cont = dbg->sourceParsed(exec,sid,body,errLine);
if (!cont) {
}
ScopeChain scopeChain;
- scopeChain.push(exec->interpreter()->globalObject().imp());
+ scopeChain.push(exec->dynamicInterpreter()->globalObject().imp());
FunctionBodyNode *bodyNode = progNode;
FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), bodyNode,
List consArgs;
- Object objCons = exec->interpreter()->builtinObject();
+ Object objCons = exec->lexicalInterpreter()->builtinObject();
Object prototype = objCons.construct(exec,List::empty());
prototype.put(exec, constructorPropertyName, Value(fimp), DontEnum|DontDelete|ReadOnly);
fimp->put(exec, prototypePropertyName, prototype, DontEnum|DontDelete|ReadOnly);
#include "error_object.h"
#include "function_object.h"
#include "internal.h"
+#include "interpreter_map.h"
#include "lexer.h"
#include "math_object.h"
#include "nodes.h"
{
List args;
args.append(const_cast<BooleanImp*>(this));
- return Object::dynamicCast(exec->interpreter()->builtinBoolean().construct(exec,args));
+ return Object::dynamicCast(exec->lexicalInterpreter()->builtinBoolean().construct(exec,args));
}
// ------------------------------ StringImp ------------------------------------
{
List args;
args.append(const_cast<StringImp*>(this));
- return Object::dynamicCast(exec->interpreter()->builtinString().construct(exec,args));
+ return Object::dynamicCast(exec->lexicalInterpreter()->builtinString().construct(exec,args));
}
// ------------------------------ NumberImp ------------------------------------
{
List args;
args.append(const_cast<NumberImp*>(this));
- return Object::dynamicCast(exec->interpreter()->builtinNumber().construct(exec,args));
+ return Object::dynamicCast(exec->lexicalInterpreter()->builtinNumber().construct(exec,args));
}
bool NumberImp::toUInt32(unsigned& uint32) const
globalInit();
}
+ InterpreterMap::setInterpreterForGlobalObject(this, glob.imp());
+
global = glob;
globExec = new ExecState(m_interpreter,0);
dbg = 0;
s_hook = 0L;
globalClear();
}
+ InterpreterMap::removeInterpreterForGlobalObject(global.imp());
+
#if APPLE_CHANGES
unlockInterpreter();
#endif
b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
}
+InterpreterImp *InterpreterImp::interpreterWithGlobalObject(ObjectImp *global)
+{
+ return InterpreterMap::getInterpreterForGlobalObject(global);
+}
+
+
// ------------------------------ InternalFunctionImp --------------------------
const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
static InterpreterImp* firstInterpreter() { return s_hook; }
InterpreterImp *nextInterpreter() const { return next; }
InterpreterImp *prevInterpreter() const { return prev; }
+
+ static InterpreterImp *interpreterWithGlobalObject(ObjectImp *);
void setContext(ContextImp *c) { _context = c; }
void Interpreter::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
+
+
+Interpreter *ExecState::lexicalInterpreter() const
+{
+ if (!_context) {
+ return dynamicInterpreter();
+ }
+
+ InterpreterImp *result = InterpreterImp::interpreterWithGlobalObject(_context->scopeChain().bottom());
+
+ if (!result) {
+ return dynamicInterpreter();
+ }
+
+ return result->interpreter();
+}
*
* @return The interpreter executing the script
*/
- Interpreter *interpreter() const { return _interpreter; }
+ Interpreter *dynamicInterpreter() const { return _interpreter; }
+
+ // for compatibility
+ Interpreter *interpreter() const { return dynamicInterpreter(); }
+
+ /**
+ * Returns the interpreter associated with the current scope's
+ * global object
+ *
+ * @return The interpreter currently in scope
+ */
+ Interpreter *lexicalInterpreter() const;
/**
* Returns the execution context associated with this execution state
--- /dev/null
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2004 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "interpreter_map.h"
+
+namespace KJS {
+
+const int _minTableSize = 64;
+
+InterpreterMap::KeyValue *InterpreterMap::_table;
+int InterpreterMap::_tableSize;
+int InterpreterMap::_tableSizeMask;
+int InterpreterMap::_keyCount;
+
+
+InterpreterImp * InterpreterMap::getInterpreterForGlobalObject(ObjectImp *global)
+{
+ if (!_table)
+ expand();
+
+ unsigned hash = computeHash(global);
+
+ int i = hash & _tableSizeMask;
+#if DUMP_STATISTICS
+ ++numProbes;
+ numCollisions += _table[i].key && _table[i].key != global;
+#endif
+ while (ObjectImp *key = _table[i].key) {
+ if (key == global) {
+ return _table[i].value;
+ }
+ i = (i + 1) & _tableSizeMask;
+ }
+
+ return 0;
+}
+
+
+void InterpreterMap::setInterpreterForGlobalObject(InterpreterImp *interpreter, ObjectImp *global)
+{
+ if (!_table)
+ expand();
+
+ unsigned hash = computeHash(global);
+
+ int i = hash & _tableSizeMask;
+#if DUMP_STATISTICS
+ ++numProbes;
+ numCollisions += _table[i].key && _table[i].key != global;
+#endif
+ while (ObjectImp *key = _table[i].key) {
+ if (key == global) {
+ _table[i].value = interpreter;
+ return;
+ }
+ i = (i + 1) & _tableSizeMask;
+ }
+
+ _table[i].key = global;
+ _table[i].value = interpreter;
+ ++_keyCount;
+
+ if (_keyCount * 2 >= _tableSize)
+ expand();
+}
+
+inline void InterpreterMap::insert(InterpreterImp *interpreter, ObjectImp *global)
+{
+ unsigned hash = computeHash(global);
+
+ int i = hash & _tableSizeMask;
+#if DUMP_STATISTICS
+ ++numProbes;
+ numCollisions += _table[i] != 0;
+#endif
+ while (_table[i].key)
+ i = (i + 1) & _tableSizeMask;
+
+ _table[i].key = global;
+ _table[i].value = interpreter;
+}
+
+void InterpreterMap::removeInterpreterForGlobalObject(ObjectImp *global)
+{
+ unsigned hash = computeHash(global);
+
+ ObjectImp *key;
+
+ int i = hash & _tableSizeMask;
+#if DUMP_STATISTICS
+ ++numProbes;
+ numCollisions += _table[i].key && _table[i].key == global;
+#endif
+ while ((key = _table[i].key)) {
+ if (key == global)
+ break;
+ i = (i + 1) & _tableSizeMask;
+ }
+ if (!key)
+ return;
+
+ _table[i].key = 0;
+ _table[i].value = 0;
+ --_keyCount;
+
+ if (_keyCount * 6 < _tableSize && _tableSize > _minTableSize) {
+ shrink();
+ return;
+ }
+
+ // Reinsert all the items to the right in the same cluster.
+ while (1) {
+ i = (i + 1) & _tableSizeMask;
+ key = _table[i].key;
+ InterpreterImp *value = _table[i].value;
+ if (!key)
+ break;
+ _table[i].key = 0;
+ _table[i].value = 0;
+ insert(value,key);
+ }
+}
+
+void InterpreterMap::expand()
+{
+ rehash(_tableSize == 0 ? _minTableSize : _tableSize * 2);
+}
+
+void InterpreterMap::shrink()
+{
+ rehash(_tableSize / 2);
+}
+
+void InterpreterMap::rehash(int newTableSize)
+{
+ int oldTableSize = _tableSize;
+ KeyValue *oldTable = _table;
+
+ _tableSize = newTableSize;
+ _tableSizeMask = newTableSize - 1;
+ _table = (KeyValue *)calloc(newTableSize, sizeof(KeyValue));
+
+ for (int i = 0; i != oldTableSize; ++i)
+ if (oldTable[i].key)
+ insert(oldTable[i].value, oldTable[i].key);
+
+ free(oldTable);
+}
+
+// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+// or anything like that.
+const unsigned PHI = 0x9e3779b9U;
+
+// This hash algorithm comes from:
+// http://burtleburtle.net/bob/hash/hashfaq.html
+// http://burtleburtle.net/bob/hash/doobs.html
+unsigned InterpreterMap::computeHash(ObjectImp *pointer)
+{
+ int length = sizeof(ObjectImp *);
+ char s[sizeof(ObjectImp *)];
+
+ memcpy((void *)s, (void *)&pointer, sizeof(ObjectImp *));
+
+ unsigned h = PHI;
+ h += length;
+ h += (h << 10);
+ h ^= (h << 6);
+
+ for (int i = 0; i < length; i++) {
+ h += (unsigned char)s[i];
+ h += (h << 10);
+ h ^= (h << 6);
+ }
+
+ h += (h << 3);
+ h ^= (h >> 11);
+ h += (h << 15);
+
+ if (h == 0)
+ h = 0x80000000;
+
+ return h;
+}
+
+
+}; // namespace
--- /dev/null
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2004 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _KJS_INTERPRETER_MAP_H_
+#define _KJS_INTERPRETER_MAP_H_
+
+namespace KJS {
+ class ObjectImp;
+ class InterpreterImp;
+
+ class InterpreterMap {
+ struct KeyValue {
+ ObjectImp *key;
+ InterpreterImp *value;
+ };
+
+ public:
+ static InterpreterImp * InterpreterMap::getInterpreterForGlobalObject(ObjectImp *global);
+ static void setInterpreterForGlobalObject(InterpreterImp *interpreter, ObjectImp *global);
+ static void removeInterpreterForGlobalObject(ObjectImp *global);
+
+ private:
+ static void insert(InterpreterImp *interpreter, ObjectImp *global);
+ static void expand();
+ static void shrink();
+ static void rehash(int newTableSize);
+ static unsigned computeHash(ObjectImp *pointer);
+
+
+ static KeyValue * InterpreterMap::_table;
+ static int InterpreterMap::_tableSize;
+ static int InterpreterMap::_tableSizeMask;
+ static int InterpreterMap::_keyCount;
+ };
+
+}; // namespace
+
+
+#endif // _KJS_INTERPRETER_MAP_H_
MathFuncImp::MathFuncImp(ExecState *exec, int i, int l)
: InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
), id(i)
{
Value protect(this);
return Completion(Normal);
#define KJS_ABORTPOINT \
- if (exec->interpreter()->imp()->debugger() && \
- exec->interpreter()->imp()->debugger()->imp()->aborted()) \
+ if (exec->dynamicInterpreter()->imp()->debugger() && \
+ exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \
return Completion(Normal);
#define KJS_CHECKEXCEPTION \
// return true if the debugger wants us to stop at this point
bool StatementNode::hitStatement(ExecState *exec)
{
- Debugger *dbg = exec->interpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
if (dbg)
return dbg->atStatement(exec,sid,l0,l1);
else
// return true if the debugger wants us to stop at this point
bool StatementNode::abortStatement(ExecState *exec)
{
- Debugger *dbg = exec->interpreter()->imp()->debugger();
+ Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
if (dbg)
return dbg->imp()->aborted();
else
list.append(p);
list.append(f);
- Object reg = exec->interpreter()->imp()->builtinRegExp();
+ Object reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
return reg.construct(exec,list);
}
// ECMA 11.1.4
Value ElementNode::evaluate(ExecState *exec)
{
- Object array = exec->interpreter()->builtinArray().construct(exec, List::empty());
+ Object array = exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty());
int length = 0;
for (ElementNode *n = this; n; n = n->list) {
Value val = n->node->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
} else {
- Value newArr = exec->interpreter()->builtinArray().construct(exec,List::empty());
+ Value newArr = exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty());
array = Object(static_cast<ObjectImp*>(newArr.imp()));
length = 0;
}
if (list)
return list->evaluate(exec);
- return exec->interpreter()->builtinObject().construct(exec,List::empty());
+ return exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
}
// ------------------------------ PropertyValueNode ----------------------------
// ECMA 11.1.5
Value PropertyValueNode::evaluate(ExecState *exec)
{
- Object obj = exec->interpreter()->builtinObject().construct(exec, List::empty());
+ Object obj = exec->lexicalInterpreter()->builtinObject().construct(exec, List::empty());
for (PropertyValueNode *p = this; p; p = p->list) {
Value n = p->name->evaluate(exec);
// of implementation we use the global object anyway here. This guarantees
// that in host objects you always get a valid object for this.
// thisVal = Null();
- thisVal = exec->interpreter()->globalObject();
+ thisVal = exec->dynamicInterpreter()->globalObject();
}
Object thisObj = Object::dynamicCast(thisVal);
FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
Object func(fimp); // protect from GC
- // Value proto = exec->interpreter()->builtinObject().construct(exec,List::empty());
+ // Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
List empty;
- Object proto = exec->interpreter()->builtinObject().construct(exec,empty);
+ Object proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
Value ret(fimp);
List empty;
- Value proto = exec->interpreter()->builtinObject().construct(exec,empty);
+ Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
int plen = 0;
// ECMA 15.7.1
Object NumberObjectImp::construct(ExecState *exec, const List &args)
{
- ObjectImp *proto = exec->interpreter()->builtinNumberPrototype().imp();
+ ObjectImp *proto = exec->lexicalInterpreter()->builtinNumberPrototype().imp();
Object obj(new NumberInstanceImp(proto));
Number n;
{
if (hint != StringType && hint != NumberType) {
/* Prefer String for Date objects */
- if (_proto == exec->interpreter()->builtinDatePrototype().imp())
+ if (_proto == exec->lexicalInterpreter()->builtinDatePrototype().imp())
hint = StringType;
else
hint = NumberType;
switch (errtype) {
case EvalError:
- cons = exec->interpreter()->builtinEvalError();
+ cons = exec->lexicalInterpreter()->builtinEvalError();
break;
case RangeError:
- cons = exec->interpreter()->builtinRangeError();
+ cons = exec->lexicalInterpreter()->builtinRangeError();
break;
case ReferenceError:
- cons = exec->interpreter()->builtinReferenceError();
+ cons = exec->lexicalInterpreter()->builtinReferenceError();
break;
case SyntaxError:
- cons = exec->interpreter()->builtinSyntaxError();
+ cons = exec->lexicalInterpreter()->builtinSyntaxError();
break;
case TypeError:
- cons = exec->interpreter()->builtinTypeError();
+ cons = exec->lexicalInterpreter()->builtinTypeError();
break;
case URIError:
- cons = exec->interpreter()->builtinURIError();
+ cons = exec->lexicalInterpreter()->builtinURIError();
break;
default:
- cons = exec->interpreter()->builtinError();
+ cons = exec->lexicalInterpreter()->builtinError();
break;
}
{
// if no arguments have been passed ...
if (args.isEmpty()) {
- Object proto = exec->interpreter()->builtinObjectPrototype();
+ Object proto = exec->lexicalInterpreter()->builtinObjectPrototype();
Object result(new ObjectImp(proto));
return result;
}
assert(!"unhandled switch case in ObjectConstructor");
case NullType:
case UndefinedType:
- Object proto = exec->interpreter()->builtinObjectPrototype();
+ Object proto = exec->lexicalInterpreter()->builtinObjectPrototype();
return Object(new ObjectImp(proto));
}
}
#endif
Value o = getBase(exec);
if (o.type() == NullType)
- o = exec->interpreter()->globalObject();
+ o = exec->dynamicInterpreter()->globalObject();
if (propertyNameIsNumber)
return static_cast<ObjectImp*>(o.imp())->put(exec,propertyNameAsNumber, w);
else
Null();
}
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp().imp());
int **ovector = regExpObj->registerRegexp( re, s.value() );
str = re->match(s.value(), i, 0L, ovector);
UString substring = lastString.substr( lastOvector[2*i], lastOvector[2*i+1] - lastOvector[2*i] );
list.append(String(substring));
}
- Object arr = exec->interpreter()->builtinArray().construct(exec, list);
+ Object arr = exec->lexicalInterpreter()->builtinArray().construct(exec, list);
arr.put(exec, "index", Number(lastOvector[0]));
arr.put(exec, "input", String(lastString));
return arr;
UString p = args.isEmpty() ? UString("") : args[0].toString(exec);
UString flags = args[1].toString(exec);
- RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->interpreter()->builtinRegExpPrototype().imp());
+ RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->lexicalInterpreter()->builtinRegExpPrototype().imp());
RegExpImp *dat = new RegExpImp(proto);
Object obj(dat); // protect from GC
}
}
+ObjectImp *ScopeChain::bottom() const
+{
+ ScopeChainNode *last;
+ for (ScopeChainNode *n = _node; n; n = n->next) {
+ if (!n->next) {
+ last = n;
+ }
+ }
+ return last->object;
+}
+
+
+
} // namespace KJS
bool isEmpty() const { return !_node; }
ObjectImp *top() const { return _node->object; }
+ ObjectImp *bottom() const;
+
void clear() { deref(); _node = 0; }
void push(ObjectImp *);
void pop();
StringProtoFuncImp::StringProtoFuncImp(ExecState *exec, int i, int len)
: InternalFunctionImp(
- static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
+ static_cast<FunctionPrototypeImp*>(exec->lexicalInterpreter()->builtinFunctionPrototype().imp())
), id(i)
{
Value protect(this);
*/
reg = tmpReg = new RegExp(a0.toString(exec), RegExp::None);
}
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp().imp());
int **ovector = regExpObj->registerRegexp(reg, u);
UString mstr = reg->match(u, -1, &pos, ovector);
if (id == Search) {
// other browsers and because Null is a false value.
result = Null();
} else {
- result = exec->interpreter()->builtinArray().construct(exec, list);
+ result = exec->lexicalInterpreter()->builtinArray().construct(exec, list);
}
}
}
if (tmp.type() != UndefinedType && tmp.toBoolean(exec) == true)
global = true;
- RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp());
+ RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp().imp());
int lastIndex = 0;
u3 = a1.toString(exec); // replacement string
// This is either a loop (if global is set) or a one-way (if not).
break;
}
case Split: {
- Object constructor = exec->interpreter()->builtinArray();
+ Object constructor = exec->lexicalInterpreter()->builtinArray();
Object res = Object::dynamicCast(constructor.construct(exec,List::empty()));
result = res;
u = s;
// ECMA 15.5.2
Object StringObjectImp::construct(ExecState *exec, const List &args)
{
- ObjectImp *proto = exec->interpreter()->builtinStringPrototype().imp();
+ ObjectImp *proto = exec->lexicalInterpreter()->builtinStringPrototype().imp();
if (args.size() == 0)
return Object(new StringInstanceImp(proto));
return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec)));
+2004-04-08 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by John.
+
+ Changed things so that newly created objects get a prototype based
+ on the scope chain of the current function, rather than the
+ interpreter that started execution. This fixes the following bugs:
+
+ <rdar://problem/3368523>: ARCH: wrong prototype used to create new objects (hang on lookup.atomica.com)
+ <rdar://problem/3559173>: ARCH: Cannot scan using a HP Jetdirect product (JS object prototypes bind incorrectly)
+
+ * khtml/ecma/kjs_binding.h:
+ (KJS::cacheDOMObject):
+ (KJS::cacheGlobalObject):
+ * khtml/ecma/kjs_css.cpp:
+ (KJS::getDOMStyleSheet):
+ (KJS::getDOMStyleSheetList):
+ (KJS::getDOMCSSValue):
+ * khtml/ecma/kjs_dom.cpp:
+ (KJS::getDOMDocumentNode):
+ (KJS::getDOMNode):
+ * khtml/ecma/kjs_events.cpp:
+ (KJS::getDOMEvent):
+ * khtml/ecma/kjs_html.cpp:
+ (KJS::HTMLDocument::tryGet):
+ (KJS::HTMLDocument::putValue):
+ (KJS::getSelectHTMLCollection):
+ * khtml/ecma/kjs_navigator.cpp:
+ (Navigator::Navigator):
+ (PluginBase::PluginBase):
+ * khtml/ecma/kjs_window.cpp:
+ (KJS::History::History):
+ (KJS::FrameArray::FrameArray):
+ (Screen::Screen):
+ (Window::retrieveActive):
+ (Window::put):
+ (Window::isSafeScript):
+ (WindowFunc::tryCall):
+ (Location::put):
+ (LocationFunc::tryCall):
+
2004-04-09 David Hyatt <hyatt@apple.com>
Fix for 3613081, repaint glitches when using overflow:auto/overlay.
DOMObject *ret;
if (domObj.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(domObj.handle())))
return Value(ret);
else {
template <class ClassCtor>
inline Object cacheGlobalObject(ExecState *exec, const Identifier &propertyName)
{
- ValueImp *obj = static_cast<ObjectImp*>(exec->interpreter()->globalObject().imp())->getDirect(propertyName);
+ ValueImp *obj = static_cast<ObjectImp*>(exec->lexicalInterpreter()->globalObject().imp())->getDirect(propertyName);
if (obj)
return Object::dynamicCast(Value(obj));
else
{
Object newObject(new ClassCtor(exec));
- exec->interpreter()->globalObject().put(exec, propertyName, newObject, Internal);
+ exec->lexicalInterpreter()->globalObject().put(exec, propertyName, newObject, Internal);
return newObject;
}
}
} \
protected: \
ClassProto( ExecState *exec ) \
- : ObjectImp( exec->interpreter()->builtinObjectPrototype() ) {} \
+ : ObjectImp( exec->lexicalInterpreter()->builtinObjectPrototype() ) {} \
\
public: \
virtual const ClassInfo *classInfo() const { return &info; } \
DOMObject *ret;
if (ss.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(ss.handle())))
return Value(ret);
else {
DOMObject *ret;
if (ssl.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(ssl.handle())))
return Value(ret);
else {
DOMObject *ret;
if (v.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(v.handle())))
return Value(ret);
else {
Value KJS::getDOMDocumentNode(ExecState *exec, const DOM::Document &n)
{
DOMDocument *ret = 0;
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = static_cast<DOMDocument *>(interp->getDOMObject(n.handle()))))
return Value(ret);
DOMObject *ret = 0;
if (n.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
DOM::NodeImpl *doc = n.ownerDocument().handle();
if ((ret = interp->getDOMObjectForDocument(static_cast<DOM::DocumentImpl *>(doc), n.handle())))
DOM::EventImpl *ei = e.handle();
if (!ei)
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
KJS::Interpreter::lock();
}
case All:
// Disable document.all when we try to be Netscape-compatible
- if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
+ if ( exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat )
return Undefined();
return getHTMLCollection(exec,doc.all());
case Clear:
// When assinging location, IE and Mozilla both resolve the URL
// relative to the frame where the JavaScript is executing not
// the target frame.
- KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->interpreter() )->part();
+ KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
if (activePart) {
KURL resolvedURL(activePart->baseURL(), str);
str = resolvedURL.url();
#if APPLE_CHANGES
// We want a new history item if this JS was called via a user gesture
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleRedirection(0, str, !userGesture);
#else
part->scheduleRedirection(0, str, false/*don't lock history*/);
DOMObject *ret;
if (c.isNull())
return Null();
- ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(c.handle())))
return Value(ret);
else {
IMPLEMENT_PROTOFUNC(NavigatorFunc)
Navigator::Navigator(ExecState *exec, KHTMLPart *p)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype()), m_part(p) { }
+ : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), m_part(p) { }
Value Navigator::get(ExecState *exec, const Identifier &propertyName) const
{
/*******************************************************************/
PluginBase::PluginBase(ExecState *exec)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype() )
+ : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype() )
{
if ( !plugins ) {
plugins = new QPtrList<PluginInfo>;
friend class HistoryFunc;
public:
History(ExecState *exec, KHTMLPart *p)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
virtual Value get(ExecState *exec, const Identifier &propertyName) const;
Value getValueProperty(ExecState *exec, int token) const;
virtual const ClassInfo* classInfo() const { return &info; }
class FrameArray : public ObjectImp {
public:
FrameArray(ExecState *exec, KHTMLPart *p)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
virtual Value get(ExecState *exec, const Identifier &propertyName) const;
virtual UString toString(ExecState *exec) const;
private:
// We set the object prototype so that toString is implemented
Screen::Screen(ExecState *exec)
- : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
+ : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
Value Screen::get(ExecState *exec, const Identifier &p) const
{
Window *Window::retrieveActive(ExecState *exec)
{
- ValueImp *imp = exec->interpreter()->globalObject().imp();
+ ValueImp *imp = exec->dynamicInterpreter()->globalObject().imp();
assert( imp );
#ifndef QWS
assert( dynamic_cast<KJS::Window*>(imp) );
QString dstUrl = p->htmlDocument().completeURL(value.toString(exec).string()).string();
if (dstUrl.find("javascript:", 0, false) || isSafeScript(exec))
{
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
#if APPLE_CHANGES
// We want a new history item if this JS was called via a user gesture
m_part->scheduleRedirection(0, dstUrl, !userGesture, userGesture);
kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
return false;
}
- KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->interpreter() )->part();
+ KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
if (!activePart) {
kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
return false;
} else if ( policy == 3 ) // smart
{
// window.open disabled unless from a key/mouse event
- if (static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture())
+ if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
#if !APPLE_CHANGES
policy = 0;
#else
// FIXME: referrer?
while ( part->parentPart() )
part = part->parentPart();
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleRedirection(0, url.url(), false/*don't lock history*/, userGesture);
return Window::retrieve(part);
}
// FIXME: referrer?
if ( part->parentPart() )
part = part->parentPart();
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleRedirection(0, url.url(), false/*don't lock history*/, userGesture);
return Window::retrieve(part);
}
}
#if APPLE_CHANGES
if (!url.isEmpty()) {
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
// FIXME: Need to pass referrer here.
khtmlpart->scheduleRedirection(0, url.url(), false, userGesture);
}
ObjectImp::put(exec, p, v, attr);
return;
}
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
#if APPLE_CHANGES
// We want a new history item if this JS was called via a user gesture
m_part->scheduleRedirection(0, url.url(), !userGesture, userGesture);
QString str = args[0].toString(exec).qstring();
KHTMLPart* p = Window::retrieveActive(exec)->part();
if ( p ) {
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleRedirection(0, p->htmlDocument().completeURL(str).string(), true /*lock history*/, userGesture);
}
break;
}
case Location::Reload:
{
- bool userGesture = static_cast<ScriptInterpreter *>(exec->interpreter())->wasRunByUserGesture();
+ bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleRedirection(0, part->url().url(), true/*lock history*/, userGesture);
break;
}