Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ed66187
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/lib
+/build
+.project
+.classpath
diff --git a/src/org/mozilla/javascript/Arguments.java b/src/org/mozilla/javascript/Arguments.java
index f7027bc..aee71f8 100644
--- a/src/org/mozilla/javascript/Arguments.java
+++ b/src/org/mozilla/javascript/Arguments.java
@@ -50,6 +50,9 @@ final class Arguments extends IdScriptableObject
     @Override
     public String getClassName()
     {
+        if (Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_ARGUMENTS_IS_OBJECT)) {
+            return "Object";
+        }
         return FTAG;
     }
 
@@ -75,7 +78,7 @@ final class Arguments extends IdScriptableObject
         putIntoActivation(index, value);
       }
       synchronized (this) {
-        if (args == activation.originalArgs) {
+        if (activation != null && args == activation.originalArgs) {
           args = args.clone();
         }
         args[index] = value;
@@ -142,6 +145,9 @@ final class Arguments extends IdScriptableObject
     @Override
     public void put(int index, Scriptable start, Object value)
     {
+        if (Context.getCurrentContext().hasFeature(Context.FEATURE_HTMLUNIT_ARGUMENTS_IS_READ_ONLY)) {
+            return;
+        }
         if (arg(index) == NOT_FOUND) {
           super.put(index, start, value);
         } else {
@@ -356,6 +362,11 @@ final class Arguments extends IdScriptableObject
       }
     }
 
+    @Override
+    public Object getDefaultValue(Class<?> typeHint) {
+        return "[object " + getClassName() + "]";
+    }
+
 // Fields to hold caller, callee and length properties,
 // where NOT_FOUND value tags deleted properties.
 // In addition if callerObj == NULL_VALUE, it tags null for scripts, as
diff --git a/src/org/mozilla/javascript/BaseFunction.java b/src/org/mozilla/javascript/BaseFunction.java
index cfc56b9..945c285 100644
--- a/src/org/mozilla/javascript/BaseFunction.java
+++ b/src/org/mozilla/javascript/BaseFunction.java
@@ -293,9 +293,6 @@ public class BaseFunction extends IdScriptableObject implements Function
     private BaseFunction realFunction(Scriptable thisObj, IdFunctionObject f)
     {
         Object x = thisObj.getDefaultValue(ScriptRuntime.FunctionClass);
-        if (x instanceof Delegator) {
-            x = ((Delegator)x).getDelegee();
-        }
         if (x instanceof BaseFunction) {
             return (BaseFunction)x;
         }
diff --git a/src/org/mozilla/javascript/CodeGenerator.java b/src/org/mozilla/javascript/CodeGenerator.java
index abc2113..55b0f3c 100644
--- a/src/org/mozilla/javascript/CodeGenerator.java
+++ b/src/org/mozilla/javascript/CodeGenerator.java
@@ -10,6 +10,7 @@ import org.mozilla.javascript.ast.AstRoot;
 import org.mozilla.javascript.ast.ScriptNode;
 import org.mozilla.javascript.ast.Jump;
 import org.mozilla.javascript.ast.FunctionNode;
+import org.mozilla.javascript.ast.VariableInitializer;
 
 /**
  * Generates bytecode for the Interpreter.
@@ -100,6 +101,7 @@ class CodeGenerator extends Icode {
           addIcode(Icode_GENERATOR);
           addUint16(theFunction.getBaseLineno() & 0xFFFF);
         }
+        itsData.declaredAsVar = (theFunction.getParent() instanceof VariableInitializer);
 
         generateICodeFromTree(theFunction.getLastChild());
     }
diff --git a/src/org/mozilla/javascript/Context.java b/src/org/mozilla/javascript/Context.java
index df4c4c0..ec63e7f 100644
--- a/src/org/mozilla/javascript/Context.java
+++ b/src/org/mozilla/javascript/Context.java
@@ -283,6 +283,104 @@ public class Context
      */
     public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13;
 
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * The same web browser (e.g. FF) may allow setting read-only property, 
+     * ignores setting the read-only property, or even throw an exception.
+     *
+     * So, by having this feature, ScriptableObject itself is asked throw
+     * {@link ScriptableObject#isReadOnlySettable} whether to allow, ignore or throw an exception.
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_ASK_OBJECT_TO_WRITE_READONLY = 14;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     * Indicates if a JavaScript catch statement can catch Java exceptions
+     * (exceptions occurring in host objects).
+     * By default {@link #hasFeature(int)} returns true.
+     */
+    public static final int FEATURE_HTMLUNIT_JS_CATCH_JAVA_EXCEPTION = 15;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Is the default value of {@link Arguments} "Object" or "Arguments"
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_ARGUMENTS_IS_OBJECT = 16;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * When setting the function name to call, call thisObject.setter.
+     *
+     * This is needed for something like "function onclick() {onclick = null}"
+     *
+     * Implemented by transforming it into "function onclick() {<b>this.</b>onclick = null}"
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_FUNCTION_NULL_SETTER = 17;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Whether the "arguments" object read-only or not.
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_ARGUMENTS_IS_READ_ONLY = 18;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Indicates that 'eval' function should have access to the local function scope.
+     *
+     * By default {@link #hasFeature(int)} returns true.
+     */
+    public static final int FEATURE_HTMLUNIT_EVAL_LOCAL_SCOPE = 19;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Indicates that 'exception' (technically NativeError) exposes "stack" property.
+     *
+     * By default {@link #hasFeature(int)} returns true.
+     */
+    public static final int FEATURE_HTMLUNIT_ERROR_STACK = 20;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Indicates that ".constructor" property is defined for all {@link ScriptableObject}s.
+     *
+     * By default {@link #hasFeature(int)} returns true.
+     */
+    public static final int FEATURE_HTMLUNIT_CONSTRUCTOR = 21;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Indicates that function can be defined as
+     * <code>function object.property() {}</code> instead of <code>object.property = function() {}</code>.
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_FUNCTION_OBJECT_METHOD = 22;
+
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Indicates that function is defined even before its declaration, inside a block.
+     *
+     * By default {@link #hasFeature(int)} returns false.
+     */
+    public static final int FEATURE_HTMLUNIT_FUNCTION_DECLARED_FORWARD_IN_BLOCK = 23;
+
     public static final String languageVersionProperty = "language version";
     public static final String errorReporterProperty   = "error reporter";
 
@@ -1325,7 +1423,7 @@ public class Context
                              securityDomain);
     }
 
-    final Script compileString(String source,
+    protected Script compileString(String source,
                                Evaluator compiler,
                                ErrorReporter compilationErrorReporter,
                                String sourceName, int lineno,
diff --git a/src/org/mozilla/javascript/ContextFactory.java b/src/org/mozilla/javascript/ContextFactory.java
index 642a3b3..3cf7974 100644
--- a/src/org/mozilla/javascript/ContextFactory.java
+++ b/src/org/mozilla/javascript/ContextFactory.java
@@ -279,6 +279,36 @@ public class ContextFactory
 
           case Context.FEATURE_ENHANCED_JAVA_ACCESS:
             return false;
+
+          case Context.FEATURE_HTMLUNIT_ASK_OBJECT_TO_WRITE_READONLY:
+            return false;
+
+          case Context.FEATURE_HTMLUNIT_JS_CATCH_JAVA_EXCEPTION:
+            return true;
+
+          case Context.FEATURE_HTMLUNIT_ARGUMENTS_IS_OBJECT:
+            return false;
+
+          case Context.FEATURE_HTMLUNIT_FUNCTION_NULL_SETTER:
+            return false;
+
+          case Context.FEATURE_HTMLUNIT_ARGUMENTS_IS_READ_ONLY:
+            return false;
+
+          case Context.FEATURE_HTMLUNIT_EVAL_LOCAL_SCOPE:
+            return true;
+
+          case Context.FEATURE_HTMLUNIT_ERROR_STACK:
+            return true;
+
+          case Context.FEATURE_HTMLUNIT_CONSTRUCTOR:
+            return true;
+
+          case Context.FEATURE_HTMLUNIT_FUNCTION_OBJECT_METHOD:
+            return false;
+
+          case Context.FEATURE_HTMLUNIT_FUNCTION_DECLARED_FORWARD_IN_BLOCK:
+            return false;
         }
         // It is a bug to call the method with unknown featureIndex
         throw new IllegalArgumentException(String.valueOf(featureIndex));
diff --git a/src/org/mozilla/javascript/Delegator.java b/src/org/mozilla/javascript/Delegator.java
index 8e8bac4..e273d0f 100644
--- a/src/org/mozilla/javascript/Delegator.java
+++ b/src/org/mozilla/javascript/Delegator.java
@@ -85,85 +85,85 @@ public class Delegator implements Function {
      * @see org.mozilla.javascript.Scriptable#getClassName
      */
     public String getClassName() {
-        return obj.getClassName();
+        return getDelegee().getClassName();
     }
     /**
      * @see org.mozilla.javascript.Scriptable#get(String, Scriptable)
      */
     public Object get(String name, Scriptable start) {
-        return obj.get(name,start);
+        return getDelegee().get(name,start);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#get(int, Scriptable)
      */
     public Object get(int index, Scriptable start) {
-        return obj.get(index,start);
+        return getDelegee().get(index,start);
         }
     /**
      * @see org.mozilla.javascript.Scriptable#has(String, Scriptable)
      */
     public boolean has(String name, Scriptable start) {
-        return obj.has(name,start);
+        return getDelegee().has(name,start);
         }
     /**
      * @see org.mozilla.javascript.Scriptable#has(int, Scriptable)
      */
     public boolean has(int index, Scriptable start) {
-        return obj.has(index,start);
+        return getDelegee().has(index,start);
         }
     /**
      * @see org.mozilla.javascript.Scriptable#put(String, Scriptable, Object)
      */
     public void put(String name, Scriptable start, Object value) {
-        obj.put(name,start,value);
+        getDelegee().put(name,start,value);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#put(int, Scriptable, Object)
      */
     public void put(int index, Scriptable start, Object value) {
-        obj.put(index,start,value);
+        getDelegee().put(index,start,value);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#delete(String)
      */
     public void delete(String name) {
-        obj.delete(name);
+        getDelegee().delete(name);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#delete(int)
      */
     public void delete(int index) {
-        obj.delete(index);
+        getDelegee().delete(index);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#getPrototype
      */
     public Scriptable getPrototype() {
-        return obj.getPrototype();
+        return getDelegee().getPrototype();
     }
     /**
      * @see org.mozilla.javascript.Scriptable#setPrototype
      */
     public void setPrototype(Scriptable prototype) {
-        obj.setPrototype(prototype);
+        getDelegee().setPrototype(prototype);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#getParentScope
      */
     public Scriptable getParentScope() {
-        return obj.getParentScope();
+        return getDelegee().getParentScope();
     }
     /**
      * @see org.mozilla.javascript.Scriptable#setParentScope
      */
     public void setParentScope(Scriptable parent) {
-        obj.setParentScope(parent);
+        getDelegee().setParentScope(parent);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#getIds
      */
     public Object[] getIds() {
-        return obj.getIds();
+        return getDelegee().getIds();
     }
     /**
      * Note that this method does not get forwarded to the delegee if
@@ -181,13 +181,13 @@ public class Delegator implements Function {
         return (hint == null ||
                 hint == ScriptRuntime.ScriptableClass ||
                 hint == ScriptRuntime.FunctionClass) ?
-            this : obj.getDefaultValue(hint);
+            this : getDelegee().getDefaultValue(hint);
     }
     /**
      * @see org.mozilla.javascript.Scriptable#hasInstance
      */
     public boolean hasInstance(Scriptable instance) {
-        return obj.hasInstance(instance);
+        return getDelegee().hasInstance(instance);
     }
     /**
      * @see org.mozilla.javascript.Function#call
@@ -195,7 +195,7 @@ public class Delegator implements Function {
     public Object call(Context cx, Scriptable scope, Scriptable thisObj,
                        Object[] args)
     {
-        return ((Function)obj).call(cx,scope,thisObj,args);
+        return ((Function)getDelegee()).call(cx,scope,thisObj,args);
     }
 
     /**
@@ -215,7 +215,7 @@ public class Delegator implements Function {
      */
     public Scriptable construct(Context cx, Scriptable scope, Object[] args)
     {
-        if (obj == null) {
+        if (getDelegee() == null) {
             //this little trick allows us to declare prototype objects for
             //Delegators
             Delegator n = newInstance();
@@ -229,7 +229,7 @@ public class Delegator implements Function {
             return n;
         }
         else {
-            return ((Function)obj).construct(cx,scope,args);
+            return ((Function)getDelegee()).construct(cx,scope,args);
         }
     }
 }
diff --git a/src/org/mozilla/javascript/FunctionObject.java b/src/org/mozilla/javascript/FunctionObject.java
index 376ef0c..600fa98 100644
--- a/src/org/mozilla/javascript/FunctionObject.java
+++ b/src/org/mozilla/javascript/FunctionObject.java
@@ -397,6 +397,9 @@ public class FunctionObject extends BaseFunction
         } else {
             if (!isStatic) {
                 Class<?> clazz = member.getDeclaringClass();
+                if (thisObj instanceof Delegator) {
+                    thisObj = ((Delegator) thisObj).getDelegee();
+                }
                 if (!clazz.isInstance(thisObj)) {
                     boolean compatible = false;
                     if (thisObj == scope) {
diff --git a/src/org/mozilla/javascript/IRFactory.java b/src/org/mozilla/javascript/IRFactory.java
index 81fb8db..ad24816 100644
--- a/src/org/mozilla/javascript/IRFactory.java
+++ b/src/org/mozilla/javascript/IRFactory.java
@@ -356,6 +356,7 @@ public final class IRFactory extends Parser
 
     private Node transformAssignment(Assignment node) {
         AstNode left = removeParens(node.getLeft());
+        left = transformAssignmentLeft(node, left);
         Node target = null;
         if (isDestructuring(left)) {
             decompile(left);
@@ -369,6 +370,32 @@ public final class IRFactory extends Parser
                                 transform(node.getRight()));
     }
 
+    private AstNode transformAssignmentLeft(Assignment node, AstNode left) {
+        AstNode right = node.getRight();
+
+        if (right.getType() == Token.NULL && node.getType() == Token.ASSIGN
+                && left instanceof Name && right instanceof KeywordLiteral
+                && Context.getCurrentContext().hasFeature(Context.FEATURE_HTMLUNIT_FUNCTION_NULL_SETTER)) {
+
+            final String identifier = ((Name) left).getIdentifier();
+            for (AstNode p = node.getParent(); p != null; p = p.getParent()) {
+                if (p instanceof FunctionNode) {
+                    final Name functionName = ((FunctionNode) p).getFunctionName();
+                    if (functionName != null && functionName.getIdentifier().equals(identifier)) {
+                        final PropertyGet propertyGet = new PropertyGet();
+                        final KeywordLiteral thisKeyword = new KeywordLiteral();
+                        thisKeyword.setType(Token.THIS);
+                        propertyGet.setLeft(thisKeyword);
+                        propertyGet.setRight(left);
+                        node.setLeft(propertyGet);
+                        return propertyGet;
+                    }
+                }
+            }
+        }
+        return left;
+    }
+
     private Node transformBlock(AstNode node) {
         if (node instanceof Scope) {
             pushScope((Scope)node);
@@ -438,6 +465,16 @@ public final class IRFactory extends Parser
     }
 
     private Node transformElementGet(ElementGet node) {
+        //Ensure "function['eval']" is transformed into "function.eval"
+        if (node.getElement().type == Token.STRING
+                && "eval".equals(((StringLiteral) node.getElement()).getValue())) {
+            final PropertyGet propertyGet = new PropertyGet();
+            propertyGet.setLeft(node.getTarget());
+            final Name name = new Name();
+            name.setIdentifier("eval");
+            propertyGet.setRight(name);
+            return transform(propertyGet);
+        }
         // OPT: could optimize to createPropertyGet
         // iff elem is string that can not be number
         Node target = transform(node.getTarget());
diff --git a/src/org/mozilla/javascript/InterpretedFunction.java b/src/org/mozilla/javascript/InterpretedFunction.java
index 92fb16a..486dc5e 100644
--- a/src/org/mozilla/javascript/InterpretedFunction.java
+++ b/src/org/mozilla/javascript/InterpretedFunction.java
@@ -16,6 +16,8 @@ final class InterpretedFunction extends NativeFunction implements Script
     SecurityController securityController;
     Object securityDomain;
 
+	private Arguments arguments;
+
     private InterpretedFunction(InterpreterData idata,
                                 Object staticSecurityDomain)
     {
@@ -176,5 +178,26 @@ final class InterpretedFunction extends NativeFunction implements Script
     {
         return idata.argIsConst[index];
     }
+
+    /**
+     * Provides the decompiled source of the function what is helpful
+     * while debugging.
+     */
+    @Override
+    public String toString() {
+    	return decompile(2, 0);
+    }
+
+	void setArguments(final Arguments arguments) {
+		this.arguments = arguments;
+	}
+	
+	@Override
+	public Object get(final String name, final Scriptable start) {
+		if (start == this && "arguments".equals(name)) {
+			return this.arguments;
+		}
+		return super.get(name, start);
+	}
 }
 
diff --git a/src/org/mozilla/javascript/Interpreter.java b/src/org/mozilla/javascript/Interpreter.java
index 485ae7c..bdbc7d3 100644
--- a/src/org/mozilla/javascript/Interpreter.java
+++ b/src/org/mozilla/javascript/Interpreter.java
@@ -2844,6 +2844,14 @@ switch (op) {
     private static void enterFrame(Context cx, CallFrame frame, Object[] args,
                                    boolean continuationRestart)
     {
+       if (frame.parentFrame != null && !frame.parentFrame.fnOrScript.isScript()) {
+           frame.fnOrScript.defaultPut("caller", frame.parentFrame.fnOrScript);
+           frame.fnOrScript.setAttributes("caller", ScriptableObject.DONTENUM);
+       }
+       if (frame.scope instanceof NativeCall) {
+           frame.fnOrScript.setArguments((Arguments) ScriptableObject.getProperty(frame.scope, "arguments"));
+       }
+
         boolean usesActivation = frame.idata.itsNeedsActivation;
         boolean isDebugged = frame.debuggerFrame != null;
         if(usesActivation || isDebugged) {
@@ -2893,6 +2901,9 @@ switch (op) {
     private static void exitFrame(Context cx, CallFrame frame,
                                   Object throwable)
     {
+        frame.fnOrScript.defaultPut("caller", null);
+        frame.fnOrScript.setArguments(null);
+
         if (frame.idata.itsNeedsActivation) {
             ScriptRuntime.exitActivationFunction(cx);
         }
diff --git a/src/org/mozilla/javascript/InterpreterData.java b/src/org/mozilla/javascript/InterpreterData.java
index 657bff4..7c9b5a0 100644
--- a/src/org/mozilla/javascript/InterpreterData.java
+++ b/src/org/mozilla/javascript/InterpreterData.java
@@ -89,6 +89,8 @@ final class InterpreterData implements Serializable, DebuggableScript
 
     boolean evalScriptFlag; // true if script corresponds to eval() code
 
+	boolean declaredAsVar; // true if the function has been declared like "var foo = function() {...}"
+
     public boolean isTopLevel()
     {
         return topLevel;
diff --git a/src/org/mozilla/javascript/MemberBox.java b/src/org/mozilla/javascript/MemberBox.java
index cc1a8cd..dc6a408 100644
--- a/src/org/mozilla/javascript/MemberBox.java
+++ b/src/org/mozilla/javascript/MemberBox.java
@@ -121,6 +121,17 @@ final class MemberBox implements Serializable
     Object invoke(Object target, Object[] args)
     {
         Method method = method();
+        
+        // handle delegators
+        if (target instanceof Delegator) {
+        	target = ((Delegator) target).getDelegee();
+        }
+        for (int i=0; i<args.length; ++i) {
+        	if (args[i] instanceof Delegator) {
+        		args[i] = ((Delegator) args[i]).getDelegee();
+        	}
+        }
+        
         try {
             try {
                 return method.invoke(target, args);
@@ -145,7 +156,22 @@ final class MemberBox implements Serializable
             } while ((e instanceof InvocationTargetException));
             if (e instanceof ContinuationPending)
                 throw (ContinuationPending) e;
-            throw Context.throwAsScriptRuntimeEx(e);
+
+            if (e instanceof RhinoException || Context.getCurrentContext().hasFeature(Context.FEATURE_HTMLUNIT_JS_CATCH_JAVA_EXCEPTION))
+                throw Context.throwAsScriptRuntimeEx(e);            
+            else
+            	throw new RuntimeException("Exception invoking " + method.getName(), e);
+        } catch (IllegalArgumentException iae) {
+            StringBuilder builder = new StringBuilder();
+            for (Object arg : args) {
+                String type = arg == null ? "null" : arg.getClass().getSimpleName();
+                if (builder.length() != 0) {
+                    builder.append(", ");
+                }
+                builder.append(type);
+            }
+            throw new IllegalArgumentException("Exception invoking " + method.getDeclaringClass().getSimpleName()
+                    + '.' +  method.getName() + "() with arguments [" + builder + "]", iae);
         } catch (Exception ex) {
             throw Context.throwAsScriptRuntimeEx(ex);
         }
diff --git a/src/org/mozilla/javascript/NativeCall.java b/src/org/mozilla/javascript/NativeCall.java
index 6094af6..1f18df5 100644
--- a/src/org/mozilla/javascript/NativeCall.java
+++ b/src/org/mozilla/javascript/NativeCall.java
@@ -6,6 +6,8 @@
 
 package org.mozilla.javascript;
 
+import org.mozilla.javascript.debug.DebuggableScript;
+
 /**
  * This class implements the activation object.
  *
@@ -61,8 +63,22 @@ public final class NativeCall extends IdScriptableObject
                 if (!super.has(name, this)) {
                     if (function.getParamOrVarConst(i))
                         defineProperty(name, Undefined.instance, CONST);
-                    else
-                        defineProperty(name, Undefined.instance, PERMANENT);
+                    else {
+                        boolean define = true;
+                        if (function instanceof InterpretedFunction) {
+                            InterpreterData idata = ((InterpretedFunction) function).idata;
+                            for (int f = 0; f < idata.getFunctionCount(); f++) {
+                                final InterpreterData functionData = (InterpreterData) idata.getFunction(f);
+								if (name.equals(functionData.getFunctionName())) {
+                                    define = functionData.declaredAsVar; // define local property only for inner functions declared with var
+                                    break;
+                                }
+                            }
+                        }
+                        if (define) {
+                            defineProperty(name, Undefined.instance, PERMANENT);
+                        }
+                    }
                 }
             }
         }
diff --git a/src/org/mozilla/javascript/NativeError.java b/src/org/mozilla/javascript/NativeError.java
index 5053c5d..e48072c 100644
--- a/src/org/mozilla/javascript/NativeError.java
+++ b/src/org/mozilla/javascript/NativeError.java
@@ -110,7 +110,7 @@ final class NativeError extends IdScriptableObject
         // generated on demand, is cached after the first access, and is
         // overwritable like an ordinary property. Hence this setup with
         // the getter and setter below.
-        if (stackProvider == null) {
+        if (stackProvider == null && Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_ERROR_STACK)) {
             stackProvider = re;
             try {
                 defineProperty("stack", null,
@@ -124,8 +124,10 @@ final class NativeError extends IdScriptableObject
     }
 
     public Object getStack() {
+    	RhinoException.useMozillaStackStyle(true);
         Object value =  stackProvider == null ?
                 NOT_FOUND : stackProvider.getScriptStackTrace();
+    	RhinoException.useMozillaStackStyle(false);
         // We store the stack as local property both to cache it
         // and to make the property writable
         setStack(value);
diff --git a/src/org/mozilla/javascript/NodeTransformer.java b/src/org/mozilla/javascript/NodeTransformer.java
index 6e0a5cd..28064c5 100644
--- a/src/org/mozilla/javascript/NodeTransformer.java
+++ b/src/org/mozilla/javascript/NodeTransformer.java
@@ -6,15 +6,16 @@
 
 package org.mozilla.javascript;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.mozilla.javascript.ast.AstRoot;
 import org.mozilla.javascript.ast.FunctionNode;
 import org.mozilla.javascript.ast.Jump;
+import org.mozilla.javascript.ast.Name;
 import org.mozilla.javascript.ast.Scope;
 import org.mozilla.javascript.ast.ScriptNode;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * This class transforms a tree to a lower-level representation for codegen.
  *
@@ -65,6 +66,34 @@ public class NodeTransformer
                                             boolean createScopeObjects,
                                             boolean inStrictMode)
     {
+        if (parent instanceof Scope
+                && Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_FUNCTION_DECLARED_FORWARD_IN_BLOCK)) {
+            // Make sure that all "Name" children are at the start of all siblings
+            Node lastInitialName = null;
+            boolean initial = true;
+            Node node = parent.getFirstChild();
+            while (node != null) {
+                if (node instanceof Name) {
+                    if (initial) {
+                        lastInitialName =  node;
+                    }
+                    else {
+                        parent.removeChild(node);
+                        if (lastInitialName == null)  {
+                            parent.addChildToFront(node);
+                        }
+                        else {
+                            parent.addChildAfter(node, lastInitialName);
+                        }
+                        lastInitialName = node;
+                    }
+                }
+                else {
+                    initial = false;
+                }
+                node = node.getNext();
+            }
+        }
         Node node = null;
       siblingLoop:
         for (;;) {
diff --git a/src/org/mozilla/javascript/Parser.java b/src/org/mozilla/javascript/Parser.java
index 7762d30..d5de488 100644
--- a/src/org/mozilla/javascript/Parser.java
+++ b/src/org/mozilla/javascript/Parser.java
@@ -533,6 +533,17 @@ public class Parser
                         n = function(calledByCompileFunction
                                      ? FunctionNode.FUNCTION_EXPRESSION
                                      : FunctionNode.FUNCTION_STATEMENT);
+                        FunctionNode functionNode = (FunctionNode) n;
+                        if (functionNode.getName().indexOf('.') != -1) {
+                            String functionName = functionNode.getName();
+                            String left = functionName.substring(0,  functionName.indexOf('.'));
+                            String right = functionName.substring(functionName.indexOf('.') + 1);
+                            PropertyGet propertyGet = new PropertyGet(new Name(0, left), new Name(0, right));
+                            Assignment assignment = new Assignment(Token.ASSIGN, propertyGet, functionNode, -1);
+                            functionNode.setFunctionName(null);
+                            functionNode.setFunctionType(FunctionNode.FUNCTION_EXPRESSION);
+                            n = new ExpressionStatement(assignment, !insideFunction());
+                        }
                     } catch (ParserException e) {
                         break;
                     }
@@ -752,12 +763,19 @@ public class Parser
                 }
             }
             if (!matchToken(Token.LP)) {
-                if (compilerEnv.isAllowMemberExprAsFunctionName()) {
-                    AstNode memberExprHead = name;
-                    name = null;
-                    memberExprNode = memberExprTail(false, memberExprHead);
+                if (Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_FUNCTION_OBJECT_METHOD)
+                        && matchToken(Token.DOT) && matchToken(Token.NAME)) {
+                    name.setIdentifier(name.getIdentifier() + '.' + createNameNode(true, Token.NAME).getIdentifier());
+                    mustMatchToken(Token.LP, "msg.no.paren.parms");
+                }
+                else {
+                    if (compilerEnv.isAllowMemberExprAsFunctionName()) {
+                        AstNode memberExprHead = name;
+                        name = null;
+                        memberExprNode = memberExprTail(false, memberExprHead);
+                    }
+                    mustMatchToken(Token.LP, "msg.no.paren.parms");
                 }
-                mustMatchToken(Token.LP, "msg.no.paren.parms");
             }
         } else if (matchToken(Token.LP)) {
             // Anonymous function:  leave name as null
diff --git a/src/org/mozilla/javascript/ScriptRuntime.java b/src/org/mozilla/javascript/ScriptRuntime.java
index e380adc..4975bbd 100644
--- a/src/org/mozilla/javascript/ScriptRuntime.java
+++ b/src/org/mozilla/javascript/ScriptRuntime.java
@@ -955,7 +955,10 @@ public class ScriptRuntime {
     public static Scriptable toObjectOrNull(Context cx, Object obj,
                                             final Scriptable scope)
     {
-        if (obj instanceof Scriptable) {
+    	if (obj instanceof Delegator) {
+    		return ((Delegator) obj).getDelegee();
+    	}
+    	else if (obj instanceof Scriptable) {
             return (Scriptable)obj;
         } else if (obj != null && obj != Undefined.instance) {
             return toObject(cx, scope, obj);
@@ -2167,6 +2170,9 @@ public class ScriptRuntime {
                                                   Context cx,
                                                   Scriptable scope)
     {
+        if ("eval".equals(name)) {
+            lastEvalTopCalled_ = true;
+        }
         Scriptable parent = scope.getParentScope();
         if (parent == null) {
             Object result = topScopeName(cx, scope, name);
@@ -2246,6 +2252,9 @@ public class ScriptRuntime {
                                                   String property,
                                                   Context cx, final Scriptable scope)
     {
+        if ("eval".equals(property)) {
+            lastEvalTopCalled_ = false;
+        }
         Scriptable thisObj = toObjectOrNull(cx, obj, scope);
         return getPropFunctionAndThisHelper(obj, property, cx, thisObj);
     }
@@ -2348,6 +2357,18 @@ public class ScriptRuntime {
         return function.construct(cx, scope, args);
     }
 
+    /**
+     * This indicates whether last call of "eval" was at the top scope (i.e. "eval()")
+     * or not (i.e. "scope.eval()"), as each one has different behavior.
+     *
+     * Ideally, we should have "eval" at top scope and we use Context.FEATURE_DYNAMIC_SCOPE,
+     * but it will complex the code.
+     *
+     * The current implementation sets this value to true when "eval" is called, and
+     * false on "something.eval()"
+     */
+    private static boolean lastEvalTopCalled_;
+    
     public static Object callSpecial(Context cx, Callable fun,
                                      Scriptable thisObj,
                                      Object[] args, Scriptable scope,
@@ -2356,6 +2377,12 @@ public class ScriptRuntime {
     {
         if (callType == Node.SPECIALCALL_EVAL) {
             if (thisObj.getParentScope() == null && NativeGlobal.isEvalFunction(fun)) {
+                final boolean isNative = scope instanceof NativeCall;
+                final boolean hasFeature = cx.hasFeature(Context.FEATURE_HTMLUNIT_EVAL_LOCAL_SCOPE);
+
+                if (!lastEvalTopCalled_ && (!hasFeature || !isNative)) {
+                    scope = thisObj;
+                }
                 return evalSpecial(cx, scope, callerThis, args,
                                    filename, lineNumber);
             }
@@ -2518,6 +2545,8 @@ public class ScriptRuntime {
             return "undefined";
         if (value instanceof ScriptableObject)
         	return ((ScriptableObject) value).getTypeOf();
+        if (value instanceof Delegator)
+            return typeof(((Delegator) value).getDelegee());
         if (value instanceof Scriptable)
             return (value instanceof Callable) ? "function" : "object";
         if (value instanceof CharSequence)
@@ -2526,6 +2555,10 @@ public class ScriptRuntime {
             return "number";
         if (value instanceof Boolean)
             return "boolean";
+        if (value instanceof MemberBox)
+            return typeof(((MemberBox) value).member());
+        if (value instanceof Method)
+            return "function";
         throw errorWithClassName("msg.invalid.type", value);
     }
 
@@ -2931,6 +2964,15 @@ public class ScriptRuntime {
             if (x instanceof Wrapper && y instanceof Wrapper) {
                 return ((Wrapper)x).unwrap() == ((Wrapper)y).unwrap();
             }
+            if (x instanceof Delegator && y instanceof Delegator) {
+                return shallowEq(((Delegator)x).getDelegee(), ((Delegator)y).getDelegee());
+            }
+            if (x instanceof Delegator && ((Delegator)x).getDelegee() == y) {
+                return true;
+            }
+            if (y instanceof Delegator && ((Delegator)y).getDelegee() == x) {
+                return true;
+            }
         } else {
             warnAboutNonJSObject(x);
             return x == y;
@@ -3160,13 +3202,27 @@ public class ScriptRuntime {
                 // Don't overwrite existing def if already defined in object
                 // or prototypes of object.
                 if (!ScriptableObject.hasProperty(scope, name)) {
-                    if (isConst) {
-                        ScriptableObject.defineConstProperty(varScope, name);
-                    } else if (!evalScript) {
+                    if (!evalScript) {
                         // Global var definitions are supposed to be DONTDELETE
-                        ScriptableObject.defineProperty(
-                            varScope, name, Undefined.instance,
-                            ScriptableObject.PERMANENT);
+                        if (isConst)
+                            ScriptableObject.defineConstProperty(varScope, name);
+                        else {
+                            boolean define = true;
+                            if (funObj instanceof InterpretedFunction) {
+                                InterpreterData idata = ((InterpretedFunction) funObj).idata;
+                                for (int f = 0; f < idata.getFunctionCount(); f++) {
+                                    if (name.equals(idata.getFunction(f).getFunctionName())) {
+                                        define = false;
+                                        break;
+                                    }
+                                }
+                            }
+                            if (define) {
+                                ScriptableObject.defineProperty(
+                                        varScope, name, Undefined.instance,
+                                        ScriptableObject.PERMANENT);
+                            }
+                        }
                     } else {
                         varScope.put(name, varScope, Undefined.instance);
                     }
diff --git a/src/org/mozilla/javascript/ScriptableObject.java b/src/org/mozilla/javascript/ScriptableObject.java
index 0ab2a98..bc4ed38 100644
--- a/src/org/mozilla/javascript/ScriptableObject.java
+++ b/src/org/mozilla/javascript/ScriptableObject.java
@@ -241,11 +241,28 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
                     if (Context.getContext().hasFeature(Context.FEATURE_STRICT_MODE)) {
                         // Based on TC39 ES3.1 Draft of 9-Feb-2009, 8.12.4, step 2,
                         // we should throw a TypeError in this case.
-                        throw ScriptRuntime.typeError1("msg.set.prop.no.setter", name);
+                        throw ScriptRuntime.typeError3("msg.set.prop.no.setter", name, start.getClassName(), Context.toString(value));
+                    }
+                    if (Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_ASK_OBJECT_TO_WRITE_READONLY)) {
+                        Scriptable scriptable = start;
+
+                        if (scriptable instanceof Delegator) {
+                            scriptable = ((Delegator) scriptable).getDelegee();
+                        }
+
+                        if (scriptable instanceof ScriptableObject) {
+                            boolean allowSetting = ((ScriptableObject) scriptable).isReadOnlySettable(name, value);
+                            if (!allowSetting) {
+                                return true;
+                            }
+                        }
+                        getter = null;
+                    }
+                    else {
+                        // Based on TC39 ES3.1 Draft of 9-Feb-2009, 8.12.4, step 2,
+                        // we should throw a TypeError in this case.
+                        throw ScriptRuntime.typeError3("msg.set.prop.no.setter", name, start.getClassName(), Context.toString(value));
                     }
-                    // Assignment to a property with only a getter defined. The
-                    // assignment is ignored. See bug 478047.
-                    return true;
                 }
             } else {
                 Context cx = Context.getContext();
@@ -2178,6 +2195,10 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
      */
     public static Object getProperty(Scriptable obj, String name)
     {
+        if ("constructor".equals(name) && !(obj instanceof IdScriptableObject)
+                && !Context.getContext().hasFeature(Context.FEATURE_HTMLUNIT_CONSTRUCTOR)) {
+            return NOT_FOUND;
+        }
         Scriptable start = obj;
         Object result;
         do {
@@ -3104,4 +3125,20 @@ public abstract class ScriptableObject implements Scriptable, Serializable,
         }
     }
 
+    /**
+     * Special to HtmlUnit's Rhino fork.
+     *
+     * Decides what to do when setting a ReadOnly property.
+     * The SimpleScriptable can return <tt>true<tt> for allowing to value to be set, <tt>false<tt> for not allowing (ignoring),
+     * or can simply throw {@link ScriptRuntime#typeError3(String, String, String, String)} with
+     * "msg.set.prop.no.setter", name, this.getClassName() and Context.toString(value).
+     *
+     * By default, this method returns <tt>true</tt>
+     * @param name the property name
+     * @param value the value
+     * @return <tt>true<tt> for allowing setting the value, <tt>false</tt> for ignoring the setting, or we can throw an exception
+     */
+    protected boolean isReadOnlySettable(final String name, final Object value) {
+        return true;
+    }
 }
diff --git a/src/org/mozilla/javascript/ast/FunctionNode.java b/src/org/mozilla/javascript/ast/FunctionNode.java
index 9589259..58b7875 100644
--- a/src/org/mozilla/javascript/ast/FunctionNode.java
+++ b/src/org/mozilla/javascript/ast/FunctionNode.java
@@ -270,7 +270,7 @@ public class FunctionNode extends ScriptNode {
      * if there is a lexical closure, or in a number of other situations.
      */
     public boolean requiresActivation() {
-        return needsActivation;
+    	return true;
     }
 
     public void setRequiresActivation() {
diff --git a/src/org/mozilla/javascript/resources/Messages.properties b/src/org/mozilla/javascript/resources/Messages.properties
index 35e4e52..c03915c 100644
--- a/src/org/mozilla/javascript/resources/Messages.properties
+++ b/src/org/mozilla/javascript/resources/Messages.properties
@@ -536,7 +536,7 @@ msg.prop.not.found =\
     Property {0} not found.
 
 msg.set.prop.no.setter =\
-    Cannot set property {0} that has only a getter.
+    Cannot set property [{1}].{0} that has only a getter to {2}.
 
 msg.invalid.type =\
     Invalid JavaScript value of type {0}
New to GrepCode? Check out our FAQ X