mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Fix following bug:
Subject: Re: Rhino: [[DefaultValue]] missing for Call object Resent-Date: Mon, 2 Jul 2001 08:52:07 -0700 (PDT) Resent-From: mozilla-jseng@mozilla.org Date: Mon, 02 Jul 2001 11:49:59 -0400 From: Norris Boyd <nboyd@atg.com> Organization: Art Technology Group To: Christopher Oliver <coliver@mminternet.com> CC: mozilla-jseng@mozilla.org References: 1 I believe the correct result of the script should be [object global] [object Object] [object global] The activation object (which goes by the name of "Call" for historical reasons) should never be the 'this' value in a function call. See "10.1.6 Activation Object" in the ECMA spec. I'll look at fixing the problem for Rhino. If there's agreement on my analysis, someone should fix this for Spidermonkey too. --N Christopher Oliver wrote: > Hi, > > function a() { > function b() { > print(this); > } > this.f = function() { > print(this); > b(); > } > b(); > } > > var a = new a(); > a.f(); > > Running the above script with SpiderMonkey produces: > > [object global] > [object Object] > [object Call] > > Running with Rhino produces the following exception: > > uncaught JavaScript exception: undefined: Cannot find default value for > object. (line 3) > > This is due to a bug in org.mozilla.javascript.NativeCall which doesn't > implement toString or valueOf or override getDefaultValue. > However, even after I hacked in an implementation of getDefaultValue in > NativeCall, Rhino still produces a different result then spidermonkey: > > [object Call] > [object Object] > [object Call]
This commit is contained in:
parent
b9b3076a0d
commit
61f8164eba
@ -61,6 +61,14 @@ public class FunctionNode extends Node {
|
||||
return itsNeedsActivation = b;
|
||||
}
|
||||
|
||||
public boolean getCheckThis() {
|
||||
return itsCheckThis;
|
||||
}
|
||||
|
||||
public void setCheckThis(boolean b) {
|
||||
itsCheckThis = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* There are three types of functions that can be defined. The first
|
||||
* is a function statement. This is a function appearing as a top-level
|
||||
@ -90,5 +98,6 @@ public class FunctionNode extends Node {
|
||||
|
||||
protected VariableTable itsVariableTable;
|
||||
protected boolean itsNeedsActivation;
|
||||
protected boolean itsCheckThis;
|
||||
protected byte itsFunctionType;
|
||||
}
|
||||
|
@ -81,6 +81,9 @@ class InterpretedFunction extends NativeFunction implements DebuggableScript {
|
||||
scope = itsClosure;
|
||||
else if (!itsData.itsUseDynamicScope)
|
||||
scope = getParentScope();
|
||||
|
||||
if (itsData.itsCheckThis)
|
||||
thisObj = ScriptRuntime.getThis(thisObj);
|
||||
|
||||
if (itsData.itsNeedsActivation) {
|
||||
scope = ScriptRuntime.initVarObj(cx, scope, this, thisObj, args);
|
||||
|
@ -66,7 +66,7 @@ public class Interpreter extends LabelTable {
|
||||
{
|
||||
version = cx.getLanguageVersion();
|
||||
itsData = new InterpreterData(0, 0, 0, securityDomain,
|
||||
cx.hasCompileFunctionsWithDynamicScope());
|
||||
cx.hasCompileFunctionsWithDynamicScope(), false);
|
||||
if (tree instanceof FunctionNode) {
|
||||
FunctionNode f = (FunctionNode) tree;
|
||||
InterpretedFunction result =
|
||||
@ -153,7 +153,8 @@ public class Interpreter extends LabelTable {
|
||||
Interpreter jsi = new Interpreter();
|
||||
jsi.itsSourceFile = itsSourceFile;
|
||||
jsi.itsData = new InterpreterData(0, 0, 0, securityDomain,
|
||||
cx.hasCompileFunctionsWithDynamicScope());
|
||||
cx.hasCompileFunctionsWithDynamicScope(),
|
||||
def.getCheckThis());
|
||||
jsi.itsData.itsFunctionType = def.getFunctionType();
|
||||
jsi.itsInFunctionFlag = true;
|
||||
jsi.debugSource = debugSource;
|
||||
|
@ -46,7 +46,7 @@ class InterpreterData {
|
||||
|
||||
InterpreterData(int lastICodeTop, int lastStringTableIndex,
|
||||
int lastNumberTableIndex, Object securityDomain,
|
||||
boolean useDynamicScope)
|
||||
boolean useDynamicScope, boolean checkThis)
|
||||
{
|
||||
itsICodeTop = lastICodeTop == 0
|
||||
? INITIAL_MAX_ICODE_LENGTH
|
||||
@ -62,6 +62,7 @@ class InterpreterData {
|
||||
: lastNumberTableIndex * 2];
|
||||
|
||||
itsUseDynamicScope = useDynamicScope;
|
||||
itsCheckThis = checkThis;
|
||||
if (securityDomain == null)
|
||||
Context.checkSecurityDomainRequired();
|
||||
this.securityDomain = securityDomain;
|
||||
@ -108,6 +109,7 @@ class InterpreterData {
|
||||
boolean itsNeedsActivation;
|
||||
boolean itsFromEvalCode;
|
||||
boolean itsUseDynamicScope;
|
||||
boolean itsCheckThis;
|
||||
byte itsFunctionType;
|
||||
|
||||
String[] itsStringTable;
|
||||
|
@ -101,12 +101,18 @@ public class NodeTransformer {
|
||||
}
|
||||
|
||||
} else {
|
||||
if (inFunction) {
|
||||
// Nested functions require activation objects.
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
}
|
||||
FunctionNode fnNode = (FunctionNode)
|
||||
node.getProp(Node.FUNCTION_PROP);
|
||||
if (inFunction) {
|
||||
// Functions containing other functions require
|
||||
// activation objects
|
||||
((FunctionNode) tree).setRequiresActivation(true);
|
||||
|
||||
// Nested functions must check their 'this' value to
|
||||
// insure it is not an activation object:
|
||||
// see 10.1.6 Activation Object
|
||||
fnNode.setCheckThis(true);
|
||||
}
|
||||
addParameters(fnNode);
|
||||
NodeTransformer inner = newInstance();
|
||||
fnNode = (FunctionNode)
|
||||
|
@ -1430,6 +1430,17 @@ public class Codegen extends Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
if (inFunction && ((OptFunctionNode)tree).getCheckThis()) {
|
||||
// Nested functions must check their 'this' value to
|
||||
// insure it is not an activation object:
|
||||
// see 10.1.6 Activation Object
|
||||
aload(thisObjLocal);
|
||||
addScriptRuntimeInvoke("getThis",
|
||||
"(Lorg/mozilla/javascript/Scriptable;)",
|
||||
"Lorg/mozilla/javascript/Scriptable;");
|
||||
astore(thisObjLocal);
|
||||
}
|
||||
|
||||
hasVarsInRegs = inFunction &&
|
||||
!((OptFunctionNode)tree).requiresActivation();
|
||||
if (hasVarsInRegs) {
|
||||
|
Loading…
Reference in New Issue
Block a user