Merge
diff --git a/make/build.xml b/make/build.xml
index 97d8954..20fcedb 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -36,9 +36,9 @@
          <pathelement location="${dist.dir}"/>
     </path>
     <path id="nashorn.boot.prefix.path">
-      <pathelement location="${dist.dir}"/>
+      <pathelement location="${dist.jar}"/>
     </path>
-    <property name="boot.class.path" value="-Xbootclasspath/a:=&quot;${toString:nashorn.boot.prefix.path}&quot;"/>
+    <property name="boot.class.path" value="-Xbootclasspath/p:&quot;${toString:nashorn.boot.prefix.path}&quot;"/>
     <condition property="svn.executable" value="/usr/local/bin/svn" else="svn">
       <available file="/usr/local/bin/svn"/>
     </condition>
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java
index 88fd89b..4193139 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java
@@ -135,15 +135,11 @@
             functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
         }
         // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
-        if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
+        if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
             final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
-            if(selfSymbol != null) {
-                if(selfSymbol.isFunctionSelf()) {
-                    selfSymbol.setNeedsSlot(false);
-                    selfSymbol.clearFlag(Symbol.IS_VAR);
-                }
-            } else {
-                assert functionNode.isProgram();
+            if(selfSymbol != null && selfSymbol.isFunctionSelf()) {
+                selfSymbol.setNeedsSlot(false);
+                selfSymbol.clearFlag(Symbol.IS_VAR);
             }
         }
         return functionNode;
@@ -189,7 +185,7 @@
      * @param body the body of the FunctionNode we are entering
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
-        // This visitor will assign symbol to all declared variables, except "var" declarations in for loop initializers.
+        // This visitor will assign symbol to all declared variables.
         body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             protected boolean enterDefault(final Node node) {
@@ -200,16 +196,17 @@
 
             @Override
             public Node leaveVarNode(final VarNode varNode) {
-                if (varNode.isStatement()) {
-                    final IdentNode ident  = varNode.getName();
-                    final Block block = varNode.isBlockScoped() ? getLexicalContext().getCurrentBlock() : body;
-                    final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
-                    if (varNode.isFunctionDeclaration()) {
-                        symbol.setIsFunctionDeclaration();
-                    }
-                    return varNode.setName(ident.setSymbol(symbol));
+                final IdentNode ident  = varNode.getName();
+                final boolean blockScoped = varNode.isBlockScoped();
+                if (blockScoped && lc.inUnprotectedSwitchContext()) {
+                    throwUnprotectedSwitchError(varNode);
                 }
-                return varNode;
+                final Block block = blockScoped ? lc.getCurrentBlock() : body;
+                final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
+                if (varNode.isFunctionDeclaration()) {
+                    symbol.setIsFunctionDeclaration();
+                }
+                return varNode.setName(ident.setSymbol(symbol));
             }
         });
     }
@@ -356,6 +353,10 @@
                         throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
                     } else {
                         symbol.setHasBeenDeclared();
+                        // Set scope flag on top-level block scoped symbols
+                        if (function.isProgram() && function.getBody() == block) {
+                            symbol.setIsScope();
+                        }
                     }
                 } else if ((flags & IS_INTERNAL) != 0) {
                     // Always create a new definition.
@@ -485,20 +486,31 @@
         final Block body = lc.getCurrentBlock();
 
         initFunctionWideVariables(functionNode, body);
+        acceptDeclarations(functionNode, body);
+        defineFunctionSelfSymbol(functionNode, body);
+    }
 
-        if (!functionNode.isProgram() && !functionNode.isDeclared() && !functionNode.isAnonymous()) {
-            // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
-            // anonymous.
-            final String name = functionNode.getIdent().getName();
-            assert name != null;
-            assert body.getExistingSymbol(name) == null;
-            defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
-            if(functionNode.allVarsInScope()) { // basically, has deep eval
-                lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
-            }
+    private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
+        // Function self-symbol is only declared as a local variable for named function expressions. Declared functions
+        // don't need it as they are local variables in their declaring scope.
+        if (!functionNode.isNamedFunctionExpression()) {
+            return;
         }
 
-        acceptDeclarations(functionNode, body);
+        final String name = functionNode.getIdent().getName();
+        assert name != null; // As it's a named function expression.
+
+        if (body.getExistingSymbol(name) != null) {
+            // Body already has a declaration for the name. It's either a parameter "function x(x)" or a
+            // top-level variable "function x() { ... var x; ... }".
+            return;
+        }
+
+        defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
+        if(functionNode.allVarsInScope()) { // basically, has deep eval
+            // We must conservatively presume that eval'd code can dynamically use the function symbol.
+            lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+        }
     }
 
     @Override
@@ -540,7 +552,7 @@
         final int flags;
         if (varNode.isAnonymousFunctionDeclaration()) {
             flags = IS_INTERNAL;
-        } else if (lc.getCurrentFunction().isProgram()) {
+        } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
             flags = IS_SCOPE;
         } else {
             flags = 0;
@@ -1044,6 +1056,15 @@
         return !(units == null || units.isEmpty());
     }
 
+    private void throwUnprotectedSwitchError(final VarNode varNode) {
+        // Block scoped declarations in switch statements without explicit blocks should be declared
+        // in a common block that contains all the case clauses. We cannot support this without a
+        // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
+        // directly contained by switch node). As a temporary solution we throw a reference error here.
+        final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
+        throwParserException(msg, varNode);
+    }
+
     private void throwParserException(final String message, final Node origin) {
         if (origin == null) {
             throw new ParserException(message);
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java
index 19197a2..dc35f96 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AstSerializer.java
@@ -48,11 +48,13 @@
     private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4);
     static byte[] serialize(final FunctionNode fn) {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
-        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out,
-                new Deflater(COMPRESSION_LEVEL)))) {
+        final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
+        try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
             oout.writeObject(removeInnerFunctionBodies(fn));
         } catch (final IOException e) {
             throw new AssertionError("Unexpected exception serializing function", e);
+        } finally {
+            deflater.end();
         }
         return out.toByteArray();
     }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
index 6e84dd8..9869c52 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -3080,6 +3080,7 @@
             if (isConditionalCatch) {
                 loadExpressionAsBoolean(exceptionCondition);
                 nextCatch = new Label("next_catch");
+                nextCatch.markAsBreakTarget();
                 method.ifeq(nextCatch);
             } else {
                 nextCatch = null;
@@ -3092,7 +3093,7 @@
                 method._goto(afterCatch);
             }
             if(nextCatch != null) {
-                method.label(nextCatch);
+                method.breakLabel(nextCatch, lc.getUsedSlotCount());
             }
         }
 
@@ -3264,6 +3265,13 @@
             emitContinueLabel(continueLabel, liveLocalsOnContinue);
         }
 
+        if (loopNode.hasPerIterationScope() && lc.getParentBlock().needsScope()) {
+            // ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
+            method.loadCompilerConstant(SCOPE);
+            method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
+            method.storeCompilerConstant(SCOPE);
+        }
+
         if(method.isReachable()) {
             if(modify != null) {
                 lineNumber(loopNode);
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java
index 724c6f1..b52d398 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java
@@ -525,7 +525,7 @@
 
         if (isAlwaysTrue(test)) {
             //turn it into a for node without a test.
-            final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, ForNode.IS_FOR).accept(this);
+            final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, 0).accept(this);
             lc.replace(whileNode, forNode);
             return forNode;
         }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java
index 3ba3f63..1bec86f 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MapCreator.java
@@ -152,6 +152,10 @@
             flags |= Property.NOT_WRITABLE;
         }
 
+        if (symbol.isBlockScoped()) {
+            flags |= Property.IS_LEXICAL_BINDING;
+        }
+
         // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError.
         if (symbol.isBlockScoped() && symbol.isScope()) {
             flags |= Property.NEEDS_DECLARATION;
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java
index e08c4d2..ee9722d 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java
@@ -45,14 +45,14 @@
     /** Iterator symbol. */
     private Symbol iterator;
 
-    /** Is this a normal for loop? */
-    public static final int IS_FOR      = 1 << 0;
-
     /** Is this a normal for in loop? */
-    public static final int IS_FOR_IN   = 1 << 1;
+    public static final int IS_FOR_IN           = 1 << 0;
 
     /** Is this a normal for each in loop? */
-    public static final int IS_FOR_EACH = 1 << 2;
+    public static final int IS_FOR_EACH         = 1 << 1;
+
+    /** Does this loop need a per-iteration scope because its init contain a LET declaration? */
+    public static final int PER_ITERATION_SCOPE = 1 << 2;
 
     private final int flags;
 
@@ -264,4 +264,9 @@
     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
+
+    @Override
+    public boolean hasPerIterationScope() {
+        return (flags & PER_ITERATION_SCOPE) != 0;
+    }
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java
index a91de69..383b9bb 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java
@@ -1091,6 +1091,15 @@
         return getFlag(USES_SELF_SYMBOL);
     }
 
+    /**
+     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
+     * anonymous function expression, and it isn't a program).
+     * @return true if this is a named function expression
+     */
+    public boolean isNamedFunctionExpression() {
+        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
+    }
+
     @Override
     public Type getType(final Function<Symbol, Type> localVariableTypes) {
         return FUNCTION_TYPE;
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java
index 2b59a07..487d6ae 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java
@@ -597,6 +597,20 @@
         throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
     }
 
+    /**
+     * Checks whether the current context is inside a switch statement without explicit blocks (curly braces).
+     * @return true if in unprotected switch statement
+     */
+    public boolean inUnprotectedSwitchContext() {
+        for (int i = sp; i > 0; i--) {
+            final LexicalContextNode next = stack[i];
+            if (next instanceof Block) {
+                return stack[i - 1] instanceof SwitchNode;
+            }
+        }
+        return false;
+    }
+
     @Override
     public String toString() {
         final StringBuffer sb = new StringBuffer();
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java
index 9e4dc42..bbc6d59 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java
@@ -177,4 +177,10 @@
      * @return new loop node if changed otherwise the same
      */
     public abstract LoopNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes);
+
+    /**
+     * Does this loop have a LET declaration and hence require a per-iteration scope?
+     * @return true if a per-iteration scope is required.
+     */
+    public abstract boolean hasPerIterationScope();
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java
index 44d7d4c..1cee8cb 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java
@@ -45,19 +45,16 @@
     /** Is this a var statement (as opposed to a "var" in a for loop statement) */
     private final int flags;
 
-    /** Flag that determines if this function node is a statement */
-    public static final int IS_STATEMENT                 = 1 << 0;
-
     /** Flag for ES6 LET declaration */
-    public static final int IS_LET                       = 1 << 1;
+    public static final int IS_LET                       = 1 << 0;
 
     /** Flag for ES6 CONST declaration */
-    public static final int IS_CONST                     = 1 << 2;
+    public static final int IS_CONST                     = 1 << 1;
 
     /** Flag that determines if this is the last function declaration in a function
      *  This is used to micro optimize the placement of return value assignments for
      *  a program node */
-    public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 3;
+    public static final int IS_LAST_FUNCTION_DECLARATION = 1 << 2;
 
     /**
      * Constructor
@@ -69,7 +66,7 @@
      * @param init       init node or null if just a declaration
      */
     public VarNode(final int lineNumber, final long token, final int finish, final IdentNode name, final Expression init) {
-        this(lineNumber, token, finish, name, init, IS_STATEMENT);
+        this(lineNumber, token, finish, name, init, 0);
     }
 
     private VarNode(final VarNode varNode, final IdentNode name, final Expression init, final int flags) {
@@ -260,14 +257,6 @@
     }
 
     /**
-     * Returns true if this is a var statement (as opposed to a var initializer in a for loop).
-     * @return true if this is a var statement (as opposed to a var initializer in a for loop).
-     */
-    public boolean isStatement() {
-        return (flags & IS_STATEMENT) != 0;
-    }
-
-    /**
      * Returns true if this is a function declaration.
      * @return true if this is a function declaration.
      */
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java
index 40bda53..e6304f4 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java
@@ -150,4 +150,9 @@
         }
         return test == null;
     }
+
+    @Override
+    public boolean hasPerIterationScope() {
+        return false;
+    }
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java
index b4f117f..6418eaf 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java
@@ -34,6 +34,7 @@
 import java.io.PrintWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.lang.invoke.SwitchPoint;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -44,6 +45,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
+import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.api.scripting.ClassFilter;
@@ -54,6 +56,8 @@
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.GlobalConstants;
 import jdk.nashorn.internal.runtime.GlobalFunctions;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.NativeJavaPackage;
@@ -69,6 +73,7 @@
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
 import jdk.nashorn.internal.scripts.JO;
 
@@ -410,13 +415,14 @@
     // Used to store the last RegExp result to support deprecated RegExp constructor properties
     private RegExpResult lastRegExpResult;
 
-    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
-    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
-    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
-    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
-    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
-    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
-    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
+    private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
+    private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
+    private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
+    private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
+    private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
+    private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
+    private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
+    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
@@ -429,6 +435,12 @@
     // current ScriptEngine associated - can be null.
     private ScriptEngine engine;
 
+    // ES6 global lexical scope.
+    private final LexicalScope lexicalScope;
+
+    // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
+    private SwitchPoint lexicalScopeSwitchPoint;
+
     /**
      * Set the current script context
      * @param scontext script context
@@ -466,6 +478,7 @@
         super(checkAndGetMap(context));
         this.context = context;
         this.setIsScope();
+        this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
     }
 
     /**
@@ -1693,6 +1706,133 @@
         splitState = state;
     }
 
+    /**
+     * Return the ES6 global scope for lexically declared bindings.
+     * @return the ES6 lexical global scope.
+     */
+    public final ScriptObject getLexicalScope() {
+        assert context.getEnv()._es6;
+        return lexicalScope;
+    }
+
+    @Override
+    public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
+        PropertyMap ownMap = getMap();
+        LexicalScope lexicalScope = null;
+        PropertyMap lexicalMap = null;
+        boolean hasLexicalDefinitions = false;
+
+        if (context.getEnv()._es6) {
+            lexicalScope = (LexicalScope) getLexicalScope();
+            lexicalMap = lexicalScope.getMap();
+
+            for (final jdk.nashorn.internal.runtime.Property property : properties) {
+                if (property.isLexicalBinding()) {
+                    hasLexicalDefinitions = true;
+                }
+                // ES6 15.1.8 steps 6. and 7.
+                final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
+                if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
+                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
+                }
+                final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
+                if (lexicalProperty != null && !property.isConfigurable()) {
+                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
+                }
+            }
+        }
+
+        for (final jdk.nashorn.internal.runtime.Property property : properties) {
+            if (property.isLexicalBinding()) {
+                assert lexicalScope != null;
+                lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
+
+                if (ownMap.findProperty(property.getKey()) != null) {
+                    // If property exists in the global object invalidate any global constant call sites.
+                    invalidateGlobalConstant(property.getKey());
+                }
+            } else {
+                ownMap = addBoundProperty(ownMap, source, property);
+            }
+        }
+
+        setMap(ownMap);
+
+        if (hasLexicalDefinitions) {
+            lexicalScope.setMap(lexicalMap);
+            invalidateLexicalSwitchPoint();
+        }
+    }
+
+    @Override
+    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
+
+        if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
+            if (lexicalScope.hasOwnProperty(name)) {
+                return lexicalScope.findGetMethod(desc, request, operator);
+            }
+        }
+
+        final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
+
+        // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
+        // because those are invalidated per-key in the addBoundProperties method above.
+        // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
+        // assuming this only applies to global constants. If other non-inherited properties will
+        // start using switchpoints some time in the future we'll have to revisit this.
+        if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
+            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
+        }
+
+        return invocation;
+    }
+
+    @Override
+    public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
+
+        if (lexicalScope != null && isScope) {
+            final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+            if (lexicalScope.hasOwnProperty(name)) {
+                return lexicalScope.findSetMethod(desc, request);
+            }
+        }
+
+        final GuardedInvocation invocation = super.findSetMethod(desc, request);
+
+        if (isScope && context.getEnv()._es6) {
+            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
+        }
+
+        return invocation;
+    }
+
+    private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
+        SwitchPoint switchPoint = lexicalScopeSwitchPoint;
+        if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
+            switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
+        }
+        return switchPoint;
+    }
+
+    private synchronized void invalidateLexicalSwitchPoint() {
+        if (lexicalScopeSwitchPoint != null) {
+            context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
+            SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
+        }
+    }
+
+
+    @SuppressWarnings("unused")
+    private static Object lexicalScopeFilter(final Object self) {
+        if (self instanceof Global) {
+            return ((Global) self).getLexicalScope();
+        }
+        return self;
+    }
+
     private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
         final T func = initConstructor(name, clazz);
         tagBuiltinProperties(name, func);
@@ -1737,7 +1877,7 @@
         this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
         this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
         this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
-        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
+        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
         this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
 
@@ -2203,4 +2343,36 @@
     protected boolean isGlobal() {
         return true;
     }
+
+    /**
+     * A class representing the ES6 global lexical scope.
+     */
+    private static class LexicalScope extends ScriptObject {
+
+        LexicalScope(final ScriptObject proto) {
+            super(proto, PropertyMap.newMap());
+        }
+
+        @Override
+        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+            return filterInvocation(super.findGetMethod(desc, request, operator));
+        }
+
+        @Override
+        protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+            return filterInvocation(super.findSetMethod(desc, request));
+        }
+
+        @Override
+        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
+            // We override this method just to make it callable by Global
+            return super.addBoundProperty(propMap, source, property);
+        }
+
+        private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
+            final MethodType type = invocation.getInvocation().type();
+            return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
+        }
+    }
+
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java
index fb50277..14c11f6 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeDataView.java
@@ -105,10 +105,10 @@
 
     private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) {
         super(Global.instance().getDataViewPrototype(), $nasgenmap$);
-        this.buffer = arrBuf;
+        this.buffer     = arrBuf;
         this.byteOffset = offset;
         this.byteLength = length;
-        this.buf = buf;
+        this.buf        = buf;
     }
 
     /**
@@ -135,14 +135,14 @@
             throw typeError("not.an.arraybuffer.in.dataview");
         }
 
-        final NativeArrayBuffer arrBuf = (NativeArrayBuffer) args[0];
+        final NativeArrayBuffer arrBuf = (NativeArrayBuffer)args[0];
         switch (args.length) {
-            case 1:
-                return new NativeDataView(arrBuf);
-            case 2:
-                return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
-            default:
-                return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
+        case 1:
+            return new NativeDataView(arrBuf);
+        case 2:
+            return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
+        default:
+            return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
         }
     }
 
@@ -995,7 +995,7 @@
 
     private static NativeDataView checkSelf(final Object self) {
         if (!(self instanceof NativeDataView)) {
-            throw typeError("not.an.arraybuffer", ScriptRuntime.safeToString(self));
+            throw typeError("not.an.arraybuffer.in.dataview", ScriptRuntime.safeToString(self));
         }
         return (NativeDataView)self;
     }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java
index c4a79a5..bd2f2dd 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java
@@ -48,6 +48,7 @@
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
 /**
  * ECMA 15.3 Function Objects
@@ -204,11 +205,7 @@
      * @return function with bound arguments
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
-    public static ScriptFunction bind(final Object self, final Object... args) {
-        if (!(self instanceof ScriptFunction)) {
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
-        }
-
+    public static Object bind(final Object self, final Object... args) {
         final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
 
         Object[] arguments;
@@ -219,7 +216,7 @@
             arguments = ScriptRuntime.EMPTY_ARRAY;
         }
 
-        return ((ScriptFunctionImpl)self).makeBoundFunction(thiz, arguments);
+        return Bootstrap.bindCallable(self, thiz, arguments);
     }
 
     /**
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java
index 7a1375d..351e5a1 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -498,7 +499,7 @@
         final Object obj = JSType.toScriptObject(self);
         if (obj instanceof ScriptObject) {
             final InvokeByName toStringInvoker = getTO_STRING();
-            final ScriptObject sobj = (ScriptObject)self;
+            final ScriptObject sobj = (ScriptObject)obj;
             try {
                 final Object toString = toStringInvoker.getGetter().invokeExact(sobj);
 
@@ -804,7 +805,7 @@
             // name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is
             // constant for any given method name and object's class.)
             return MethodHandles.dropArguments(MethodHandles.constant(Object.class,
-                    Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class);
+                    Bootstrap.bindCallable(methodGetter.invoke(source), source, null)), 0, Object.class);
         } catch(RuntimeException|Error e) {
             throw e;
         } catch(final Throwable t) {
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index 36e7716..f147234 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -30,7 +30,6 @@
 
 import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
-
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.GlobalFunctions;
 import jdk.nashorn.internal.runtime.Property;
@@ -237,13 +236,13 @@
 
     /**
      * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
-     * can expose it to methods in this package.
+     * can expose it.
      * @param self the self to bind to this function. Can be null (in which case, null is bound as this).
      * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
      * @return a function with the specified self and parameters bound.
      */
     @Override
-    protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
+    public ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
         return super.makeBoundFunction(self, args);
     }
 
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
index 32f1df6..ed078df 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
@@ -554,7 +554,7 @@
         // Set up new block. Captures first token.
         final ParserContextBlockNode newBlock = newBlock();
         try {
-            statement();
+            statement(false, false, true);
         } finally {
             restoreBlock(newBlock);
         }
@@ -703,26 +703,12 @@
                 Collections.<IdentNode>emptyList());
         lc.push(script);
         final ParserContextBlockNode body = newBlock();
-        // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations.
-        final int startLine = start;
-        final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
-        functionDeclarations = new ArrayList<>();
 
-        try {
-            sourceElements(allowPropertyFunction);
-            addFunctionDeclarations(script);
-        } finally {
-            if (outer != null) {
-                restoreBlock(outer);
-                appendStatement(new BlockStatement(
-                        startLine,
-                        new Block(
-                                functionToken,
-                                startLine, outer.getFlags(),
-                                outer.getStatements())));
-            }
-        }
+        functionDeclarations = new ArrayList<>();
+        sourceElements(allowPropertyFunction);
+        addFunctionDeclarations(script);
         functionDeclarations = null;
+
         restoreBlock(body);
         body.setFlag(Block.NEEDS_SCOPE);
         final Block programBody = new Block(functionToken, functionLine, body.getFlags(), body.getStatements());
@@ -784,7 +770,7 @@
 
                 try {
                     // Get the next element.
-                    statement(true, allowPropertyFunction);
+                    statement(true, allowPropertyFunction, false);
                     allowPropertyFunction = false;
 
                     // check for directive prologues
@@ -874,13 +860,15 @@
      * Parse any of the basic statement types.
      */
     private void statement() {
-        statement(false, false);
+        statement(false, false, false);
     }
 
     /**
      * @param topLevel does this statement occur at the "top level" of a script or a function?
+     * @param allowPropertyFunction allow property "get" and "set" functions?
+     * @param singleStatement are we in a single statement context?
      */
-    private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
+    private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
         if (type == FUNCTION) {
             // As per spec (ECMA section 12), function declarations as arbitrary statement
             // is not "portable". Implementation can issue a warning or disallow the same.
@@ -944,6 +932,9 @@
             break;
         default:
             if (useBlockScope() && (type == LET || type == CONST)) {
+                if (singleStatement) {
+                    throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
+                }
                 variableStatement(type, true);
                 break;
             }
@@ -1069,7 +1060,7 @@
         next();
 
         final List<VarNode> vars = new ArrayList<>();
-        int varFlags = VarNode.IS_STATEMENT;
+        int varFlags = 0;
         if (varType == LET) {
             varFlags |= VarNode.IS_LET;
         } else if (varType == CONST) {
@@ -1214,7 +1205,6 @@
         final int startLine = start;
         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
 
-
         // Create FOR node, capturing FOR token.
         final ParserContextLoopNode forNode = new ParserContextLoopNode();
         lc.push(forNode);
@@ -1242,19 +1232,22 @@
 
             switch (type) {
             case VAR:
-                // Var statements captured in for outer block.
+                // Var declaration captured in for outer block.
                 vars = variableStatement(type, false);
                 break;
             case SEMICOLON:
                 break;
             default:
                 if (useBlockScope() && (type == LET || type == CONST)) {
-                    // LET/CONST captured in container block created above.
+                    if (type == LET) {
+                        flags |= ForNode.PER_ITERATION_SCOPE;
+                    }
+                    // LET/CONST declaration captured in container block created above.
                     vars = variableStatement(type, false);
                     break;
                 }
                 if (env._const_as_var && type == CONST) {
-                    // Var statements captured in for outer block.
+                    // Var declaration captured in for outer block.
                     vars = variableStatement(TokenType.VAR, false);
                     break;
                 }
@@ -1330,21 +1323,22 @@
             body = getStatement();
         } finally {
             lc.pop(forNode);
-            if (vars != null) {
-                for (final VarNode var : vars) {
-                    appendStatement(var);
-                }
+        }
+
+        if (vars != null) {
+            for (final VarNode var : vars) {
+                appendStatement(var);
             }
-            if (body != null) {
-                appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
-            }
-            if (outer != null) {
-                restoreBlock(outer);
-                appendStatement(new BlockStatement(startLine, new Block(
-                        outer.getToken(),
-                        body.getFinish(),
-                        outer.getStatements())));
-            }
+        }
+        if (body != null) {
+            appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
+        }
+        if (outer != null) {
+            restoreBlock(outer);
+            appendStatement(new BlockStatement(startLine, new Block(
+                    outer.getToken(),
+                    body.getFinish(),
+                    outer.getStatements())));
         }
     }
 
@@ -1378,9 +1372,10 @@
             body = getStatement();
         } finally {
             lc.pop(whileNode);
-            if (body != null){
-              appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
-            }
+        }
+
+        if (body != null) {
+            appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
         }
     }
 
@@ -1422,8 +1417,9 @@
             }
         } finally {
             lc.pop(doWhileNode);
-            appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
         }
+
+        appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
     }
 
     /**
@@ -1621,17 +1617,12 @@
             throw error(AbstractParser.message("strict.no.with"), withToken);
         }
 
-        Expression expression = null;
-        Block body = null;
-        try {
-            expect(LPAREN);
-            expression = expression();
-            expect(RPAREN);
-            body = getStatement();
-        } finally {
-            appendStatement(new WithNode(withLine, withToken, finish, expression, body));
-        }
+        expect(LPAREN);
+        final Expression expression = expression();
+        expect(RPAREN);
+        final Block body = getStatement();
 
+        appendStatement(new WithNode(withLine, withToken, finish, expression, body));
     }
 
     /**
@@ -1720,8 +1711,9 @@
             next();
         } finally {
             lc.pop(switchNode);
-            appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
         }
+
+        appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
     }
 
     /**
@@ -1752,10 +1744,9 @@
         } finally {
             assert lc.peek() instanceof ParserContextLabelNode;
             lc.pop(labelNode);
-            if (ident != null){
-              appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
-            }
         }
+
+        appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
     }
 
     /**
@@ -2300,9 +2291,14 @@
         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
         lc.push(functionNode);
 
-        final Block functionBody = functionBody(functionNode);
+        Block functionBody;
 
-        lc.pop(functionNode);
+
+        try {
+            functionBody = functionBody(functionNode);
+        } finally {
+            lc.pop(functionNode);
+        }
 
         final FunctionNode  function = createFunctionNode(
                 functionNode,
@@ -2340,9 +2336,13 @@
         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
         lc.push(functionNode);
 
-        final Block functionBody = functionBody(functionNode);
+        Block functionBody;
+        try {
+            functionBody = functionBody(functionNode);
+        } finally {
+            lc.pop(functionNode);
+        }
 
-        lc.pop(functionNode);
 
         final FunctionNode  function = createFunctionNode(
                 functionNode,
@@ -2739,12 +2739,9 @@
                 functionBody);
 
         if (isStatement) {
-            int varFlags = VarNode.IS_STATEMENT;
-            if (!topLevel && useBlockScope()) {
-                // mark ES6 block functions as lexically scoped
-                varFlags |= VarNode.IS_LET;
-            }
-            final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
+            // mark ES6 block functions as lexically scoped
+            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
+            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
             if (topLevel) {
                 functionDeclarations.add(varNode);
             } else if (useBlockScope()) {
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java
index 8c9c96a..ec0d2d0 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java
@@ -25,7 +25,7 @@
 package jdk.nashorn.internal.parser;
 
 /**
- * A ParserContextNode that represents a SwithcNode that is currently being parsed
+ * A ParserContextNode that represents a SwitchNode that is currently being parsed
  */
 class ParserContextSwitchNode extends ParserContextBaseNode implements ParserContextBreakableNode {
 
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java
index 8f27661..9a557cf 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AstDeserializer.java
@@ -27,6 +27,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.zip.InflaterInputStream;
 import jdk.nashorn.internal.ir.FunctionNode;
 
@@ -36,12 +38,18 @@
  */
 final class AstDeserializer {
     static FunctionNode deserialize(final byte[] serializedAst) {
-        try {
-            return (FunctionNode)new ObjectInputStream(new InflaterInputStream(new ByteArrayInputStream(
-                    serializedAst))).readObject();
-        } catch (final ClassNotFoundException | IOException e) {
-            // This is internal, can't happen
-            throw new AssertionError("Unexpected exception deserializing function", e);
-        }
+        // FIXME: do we need this doPrivileged block at all?
+        return AccessController.doPrivileged(new PrivilegedAction<FunctionNode>() {
+            @Override
+            public FunctionNode run() {
+                try {
+                    return (FunctionNode)new ObjectInputStream(new InflaterInputStream(
+                        new ByteArrayInputStream(serializedAst))).readObject();
+                } catch (final ClassNotFoundException | IOException e) {
+                    // This is internal, can't happen
+                    throw new AssertionError("Unexpected exception deserializing function", e);
+                }
+            }
+        });
     }
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java
index 75395ea..7e54b1e 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java
@@ -714,6 +714,9 @@
      * @return a number
      */
     public static double toNumber(final Object obj) {
+        if (obj instanceof Double) {
+            return (Double)obj;
+        }
         if (obj instanceof Number) {
             return ((Number)obj).doubleValue();
         }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
index 41baa64..4225c25 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
@@ -84,14 +84,17 @@
     public static final int IS_NASGEN_PRIMITIVE     = 1 << 6;
 
     /** Is this a builtin property, e.g. Function.prototype.apply */
-    public static final int IS_BUILTIN = 1 << 7;
+    public static final int IS_BUILTIN              = 1 << 7;
 
     /** Is this property bound to a receiver? This means get/set operations will be delegated to
      *  a statically defined object instead of the object passed as callsite parameter. */
-    public static final int IS_BOUND                = 1 << 7;
+    public static final int IS_BOUND                = 1 << 8;
 
     /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */
-    public static final int NEEDS_DECLARATION       = 1 << 8;
+    public static final int NEEDS_DECLARATION       = 1 << 9;
+
+    /** Is this property an ES6 lexical binding? */
+    public static final int IS_LEXICAL_BINDING      = 1 << 10;
 
     /** Property key. */
     private final String key;
@@ -714,4 +717,12 @@
     public boolean isFunctionDeclaration() {
         return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
     }
+
+    /**
+     * Is this a property defined by ES6 let or const?
+     * @return true if this property represents a lexical binding.
+     */
+    public boolean isLexicalBinding() {
+        return (flags & IS_LEXICAL_BINDING) == IS_LEXICAL_BINDING;
+    }
 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
index 8924624..3f60591 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -46,6 +46,8 @@
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
 
 import java.lang.invoke.MethodHandle;
@@ -98,7 +100,7 @@
  * </ul>
  */
 
-public abstract class ScriptObject implements PropertyAccess {
+public abstract class ScriptObject implements PropertyAccess, Cloneable {
     /** __proto__ special property name inside object literals. ES6 draft. */
     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 
@@ -304,32 +306,47 @@
         PropertyMap newMap = this.getMap();
 
         for (final Property property : properties) {
-            final String key = property.getKey();
-            final Property oldProp = newMap.findProperty(key);
-            if (oldProp == null) {
-                if (property instanceof UserAccessorProperty) {
-                    // Note: we copy accessor functions to this object which is semantically different from binding.
-                    final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
-                    newMap = newMap.addPropertyNoHistory(prop);
-                } else {
-                    newMap = newMap.addPropertyBind((AccessorProperty)property, source);
-                }
-            } else {
-                // See ECMA section 10.5 Declaration Binding Instantiation
-                // step 5 processing each function declaration.
-                if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
-                     if (oldProp instanceof UserAccessorProperty ||
-                         !(oldProp.isWritable() && oldProp.isEnumerable())) {
-                         throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
-                     }
-                }
-            }
+            newMap = addBoundProperty(newMap, source, property);
         }
 
         this.setMap(newMap);
     }
 
     /**
+     * Add a bound property from {@code source}, using the interim property map {@code propMap}, and return the
+     * new interim property map.
+     *
+     * @param propMap the property map
+     * @param source the source object
+     * @param property the property to be added
+     * @return the new property map
+     */
+    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
+        PropertyMap newMap = propMap;
+        final String key = property.getKey();
+        final Property oldProp = newMap.findProperty(key);
+        if (oldProp == null) {
+            if (property instanceof UserAccessorProperty) {
+                // Note: we copy accessor functions to this object which is semantically different from binding.
+                final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
+                newMap = newMap.addPropertyNoHistory(prop);
+            } else {
+                newMap = newMap.addPropertyBind((AccessorProperty)property, source);
+            }
+        } else {
+            // See ECMA section 10.5 Declaration Binding Instantiation
+            // step 5 processing each function declaration.
+            if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
+                if (oldProp instanceof UserAccessorProperty ||
+                        !(oldProp.isWritable() && oldProp.isEnumerable())) {
+                    throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
+                }
+            }
+        }
+        return newMap;
+    }
+
+    /**
      * Copy all properties from the array with their receiver bound to the source.
      *
      * @param source The source object to copy from.
@@ -510,7 +527,11 @@
         }
     }
 
-    private void invalidateGlobalConstant(final String key) {
+    /**
+     * Invalidate any existing global constant method handles that may exist for {@code key}.
+     * @param key the property name
+     */
+    protected void invalidateGlobalConstant(final String key) {
         final GlobalConstants globalConstants = getGlobalConstants();
         if (globalConstants != null) {
             globalConstants.delete(key);
@@ -2183,6 +2204,9 @@
 
         if (find != null) {
             if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
+                if (NashornCallSiteDescriptor.isScope(desc) && find.getProperty().isLexicalBinding()) {
+                    throw typeError("assign.constant", name); // Overwriting ES6 const should throw also in non-strict mode.
+                }
                 // Existing, non-writable property
                 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
             }
@@ -3084,7 +3108,7 @@
     private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
         if (longIndex >= oldLength) {
             if (!isExtensible()) {
-                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+                if (isStrictFlag(callSiteFlags)) {
                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
                 }
                 return true;
@@ -3108,7 +3132,7 @@
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
@@ -3118,7 +3142,7 @@
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
@@ -3128,7 +3152,7 @@
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
@@ -3138,7 +3162,7 @@
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
@@ -3159,7 +3183,7 @@
         invalidateGlobalConstant(key);
 
         if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
-            final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
+            final boolean isScope = isScopeFlag(callSiteFlags);
             // If the start object of the find is not this object it means the property was found inside a
             // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
             // to the 'with' object.
@@ -3180,16 +3204,19 @@
 
         if (f != null) {
             if (!f.getProperty().isWritable()) {
-                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+                if (isScopeFlag(callSiteFlags) && f.getProperty().isLexicalBinding()) {
+                    throw typeError("assign.constant", key); // Overwriting ES6 const should throw also in non-strict mode.
+                }
+                if (isStrictFlag(callSiteFlags)) {
                     throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
                 }
                 return;
             }
 
-            f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
+            f.setValue(value, isStrictFlag(callSiteFlags));
 
         } else if (!isExtensible()) {
-            if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+            if (isStrictFlag(callSiteFlags)) {
                 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
             }
         } else {
@@ -3216,7 +3243,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3236,7 +3263,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3256,7 +3283,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3276,7 +3303,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3295,7 +3322,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3314,7 +3341,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3333,7 +3360,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3352,7 +3379,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3371,7 +3398,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3390,7 +3417,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3409,7 +3436,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3428,7 +3455,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3446,7 +3473,7 @@
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 final ArrayData data = getArray();
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3464,7 +3491,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3483,7 +3510,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3502,7 +3529,7 @@
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
@@ -3667,6 +3694,29 @@
     }
 
     /**
+     * Return a shallow copy of this ScriptObject.
+     * @return a shallow copy.
+     */
+    public final ScriptObject copy() {
+        try {
+            return clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    protected ScriptObject clone() throws CloneNotSupportedException {
+        final ScriptObject clone = (ScriptObject) super.clone();
+        if (objectSpill != null) {
+            clone.objectSpill = objectSpill.clone();
+            clone.primitiveSpill = primitiveSpill.clone();
+        }
+        clone.arrayData = arrayData.copy();
+        return clone;
+    }
+
+    /**
      * Make a new UserAccessorProperty property. getter and setter functions are stored in
      * this ScriptObject and slot values are used in property object.
      *
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index b018596..f0a8c7a 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -61,9 +61,9 @@
     /**
      * Length of the array data. Not necessarily length of the wrapped array.
      * This is private to ensure that no one in a subclass is able to touch the length
-     * without going through {@link setLength}. This is used to implement
+     * without going through {@link #setLength}. This is used to implement
      * {@link LengthNotWritableFilter}s, ensuring that there are no ways past
-     * a {@link setLength} function replaced by a nop
+     * a {@link #setLength} function replaced by a nop
      */
     private long length;
 
@@ -79,11 +79,7 @@
      */
     private static class UntouchedArrayData extends ContinuousArrayData {
         private UntouchedArrayData() {
-            this(0);
-        }
-
-        private UntouchedArrayData(final int length) {
-            super(length);
+            super(0);
         }
 
         private ArrayData toRealArrayData() {
@@ -100,7 +96,8 @@
 
         @Override
         public ContinuousArrayData copy() {
-            return new UntouchedArrayData((int)length());
+            assert length() == 0;
+            return this;
         }
 
         @Override
@@ -246,7 +243,7 @@
         public Class<?> getBoxedElementType() {
             return Integer.class;
         }
-    };
+    }
 
     /**
      * Constructor
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
index 244739b..ff4c13e 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
@@ -25,11 +25,7 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
-import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -98,17 +94,7 @@
      * @return result of apply
      */
     public final T apply() {
-        final boolean strict;
-        if (callbackfn instanceof ScriptFunction) {
-            strict = ((ScriptFunction)callbackfn).isStrict();
-        } else if (callbackfn instanceof JSObject &&
-            ((JSObject)callbackfn).isFunction()) {
-            strict = ((JSObject)callbackfn).isStrictFunction();
-        } else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) {
-            strict = false;
-        } else {
-            throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
-        }
+        final boolean strict = Bootstrap.isStrictCallable(callbackfn);
 
         // for non-strict callback, need to translate undefined thisArg to be global object
         thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java
index 8c270fb..749c472 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime.linker;
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
 import java.lang.invoke.CallSite;
 import java.lang.invoke.ConstantCallSite;
@@ -50,6 +51,8 @@
 import jdk.nashorn.internal.codegen.RuntimeCallSite;
 import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.objects.ScriptFunctionImpl;
+import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
 import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -94,7 +97,7 @@
             new NashornLinker(),
             new NashornPrimitiveLinker(),
             new NashornStaticClassLinker(),
-            new BoundDynamicMethodLinker(),
+            new BoundCallableLinker(),
             new JavaSuperAdapterLinker(),
             new JSObjectLinker(nashornBeansLinker),
             new BrowserJSObjectLinker(nashornBeansLinker),
@@ -136,19 +139,47 @@
         }
 
         return obj instanceof ScriptFunction ||
-            ((obj instanceof JSObject) && ((JSObject)obj).isFunction()) ||
-            isDynamicMethod(obj) ||
+            isJSObjectFunction(obj) ||
+            BeansLinker.isDynamicMethod(obj) ||
+            obj instanceof BoundCallable ||
             isFunctionalInterfaceObject(obj) ||
             obj instanceof StaticClass;
     }
 
     /**
+     * Returns true if the given object is a strict callable
+     * @param callable the callable object to be checked for strictness
+     * @return true if the obj is a strict callable, false if it is a non-strict callable.
+     * @throws ECMAException with {@code TypeError} if the object is not a callable.
+     */
+    public static boolean isStrictCallable(final Object callable) {
+        if (callable instanceof ScriptFunction) {
+            return ((ScriptFunction)callable).isStrict();
+        } else if (isJSObjectFunction(callable)) {
+            return ((JSObject)callable).isStrictFunction();
+        } else if (callable instanceof BoundCallable) {
+            return isStrictCallable(((BoundCallable)callable).getCallable());
+        } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) {
+            return false;
+        }
+        throw notFunction(callable);
+    }
+
+    private static ECMAException notFunction(final Object obj) {
+        return typeError("not.a.function", ScriptRuntime.safeToString(obj));
+    }
+
+    private static boolean isJSObjectFunction(final Object obj) {
+        return obj instanceof JSObject && ((JSObject)obj).isFunction();
+    }
+
+    /**
      * Returns if the given object is a dynalink Dynamic method
      * @param obj object to be checked
      * @return true if the obj is a dynamic method
      */
     public static boolean isDynamicMethod(final Object obj) {
-        return obj instanceof BoundDynamicMethod || BeansLinker.isDynamicMethod(obj);
+        return BeansLinker.isDynamicMethod(obj instanceof BoundCallable ? ((BoundCallable)obj).getCallable() : obj);
     }
 
     /**
@@ -370,14 +401,22 @@
     }
 
     /**
-     * Binds a bean dynamic method (returned by invoking {@code dyn:getMethod} on an object linked with
-     * {@code BeansLinker} to a receiver.
-     * @param dynamicMethod the dynamic method to bind
+     * Binds any object Nashorn can use as a [[Callable]] to a receiver and optionally arguments.
+     * @param callable the callable to bind
      * @param boundThis the bound "this" value.
-     * @return a bound dynamic method.
+     * @param boundArgs the bound arguments. Can be either null or empty array to signify no arguments are bound.
+     * @return a bound callable.
+     * @throws ECMAException with {@code TypeError} if the object is not a callable.
      */
-    public static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
-        return new BoundDynamicMethod(dynamicMethod, boundThis);
+    public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
+        if (callable instanceof ScriptFunctionImpl) {
+            return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
+        } else if (callable instanceof BoundCallable) {
+            return ((BoundCallable)callable).bind(boundArgs);
+        } else if (isCallable(callable)) {
+            return new BoundCallable(callable, boundThis, boundArgs);
+        }
+        throw notFunction(callable);
     }
 
     /**
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallable.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallable.java
new file mode 100644
index 0000000..a0eee0d
--- /dev/null
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallable.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import java.util.Arrays;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Represents a Nashorn callable bound to a receiver and optionally arguments. Note that objects of this class
+ * are just the tuples of a callable and a bound this and arguments, without any behavior. All the behavior is
+ * defined in the {@code BoundCallableLinker}.
+ */
+public final class BoundCallable {
+    private final Object callable;
+    private final Object boundThis;
+    private final Object[] boundArgs;
+
+    BoundCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
+        this.callable = callable;
+        this.boundThis = boundThis;
+        this.boundArgs = isEmptyArray(boundArgs) ? ScriptRuntime.EMPTY_ARRAY : boundArgs.clone();
+    }
+
+    private BoundCallable(final BoundCallable original, final Object[] extraBoundArgs) {
+        this.callable = original.callable;
+        this.boundThis = original.boundThis;
+        this.boundArgs = original.concatenateBoundArgs(extraBoundArgs);
+    }
+
+    Object getCallable() {
+        return callable;
+    }
+
+    Object getBoundThis() {
+        return boundThis;
+    }
+
+    Object[] getBoundArgs() {
+        return boundArgs;
+    }
+
+    BoundCallable bind(final Object[] extraBoundArgs) {
+        if (isEmptyArray(extraBoundArgs)) {
+            return this;
+        }
+        return new BoundCallable(this, extraBoundArgs);
+    }
+
+    private Object[] concatenateBoundArgs(final Object[] extraBoundArgs) {
+        if (boundArgs.length == 0) {
+            return extraBoundArgs.clone();
+        }
+        final int origBoundArgsLen = boundArgs.length;
+        final int extraBoundArgsLen = extraBoundArgs.length;
+        final Object[] newBoundArgs = new Object[origBoundArgsLen + extraBoundArgsLen];
+        System.arraycopy(boundArgs, 0, newBoundArgs, 0, origBoundArgsLen);
+        System.arraycopy(extraBoundArgs, 0, newBoundArgs, origBoundArgsLen, extraBoundArgsLen);
+        return newBoundArgs;
+    }
+
+    private static boolean isEmptyArray(final Object[] a) {
+        return a == null || a.length == 0;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder b = new StringBuilder(callable.toString()).append(" on ").append(boundThis);
+        if (boundArgs.length != 0) {
+            b.append(" with ").append(Arrays.toString(boundArgs));
+        }
+        return b.toString();
+    }
+}
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
new file mode 100644
index 0000000..d52063b
--- /dev/null
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.Guards;
+
+/**
+ * Links {@link BoundCallable} objects. Passes through to linker services for linking a callable (for either
+ * "dyn:call" or "dyn:new"), and modifies the returned invocation to deal with the receiver and argument binding.
+ */
+final class BoundCallableLinker implements TypeBasedGuardingDynamicLinker {
+    @Override
+    public boolean canLinkType(final Class<?> type) {
+        return type == BoundCallable.class;
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
+        final Object objBoundCallable = linkRequest.getReceiver();
+        if(!(objBoundCallable instanceof BoundCallable)) {
+            return null;
+        }
+
+        final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
+        if (descriptor.getNameTokenCount() < 2 || !"dyn".equals(descriptor.getNameToken(CallSiteDescriptor.SCHEME))) {
+            return null;
+        }
+        final String operation = descriptor.getNameToken(CallSiteDescriptor.OPERATOR);
+        // We need to distinguish "dyn:new" from "dyn:call" because "dyn:call" sites have parameter list of the form
+        // "callee, this, args", while "dyn:call" sites have "callee, args" -- they lack the "this" parameter.
+        final boolean isCall;
+        if ("new".equals(operation)) {
+            isCall = false;
+        } else if ("call".equals(operation)) {
+            isCall = true;
+        } else {
+            // Only dyn:call and dyn:new are supported.
+            return null;
+        }
+        final BoundCallable boundCallable = (BoundCallable)objBoundCallable;
+        final Object callable = boundCallable.getCallable();
+        final Object boundThis = boundCallable.getBoundThis();
+
+        // We need to ask the linker services for a delegate invocation on the target callable.
+
+        // Replace arguments (boundCallable[, this], args) => (callable[, boundThis], boundArgs, args) when delegating
+        final Object[] args = linkRequest.getArguments();
+        final Object[] boundArgs = boundCallable.getBoundArgs();
+        final int argsLen = args.length;
+        final int boundArgsLen = boundArgs.length;
+        final Object[] newArgs = new Object[argsLen + boundArgsLen];
+        newArgs[0] = callable;
+        final int firstArgIndex;
+        if (isCall) {
+            newArgs[1] = boundThis;
+            firstArgIndex = 2;
+        } else {
+            firstArgIndex = 1;
+        }
+        System.arraycopy(boundArgs, 0, newArgs, firstArgIndex, boundArgsLen);
+        System.arraycopy(args, firstArgIndex, newArgs, firstArgIndex + boundArgsLen, argsLen - firstArgIndex);
+
+        // Use R(T0, T1, T2, ...) => R(callable.class, boundThis.class, boundArg0.class, ..., boundArgn.class, T2, ...)
+        // call site type when delegating to underlying linker (for dyn:new, there's no this).
+        final MethodType type = descriptor.getMethodType();
+        // Use R(T0, ...) => R(callable.class, ...)
+        MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass());
+        if (isCall) {
+            // R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...)
+            newMethodType = newMethodType.changeParameterType(1, boundThis.getClass());
+        }
+        // R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...)
+        for(int i = boundArgs.length; i-- > 0;) {
+            newMethodType = newMethodType.insertParameterTypes(firstArgIndex, boundArgs[i] == null ? Object.class : boundArgs[i].getClass());
+        }
+        final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(newMethodType);
+
+        // Delegate to target's linker
+        final GuardedInvocation inv = linkerServices.getGuardedInvocation(linkRequest.replaceArguments(newDescriptor, newArgs));
+        if(inv == null) {
+            return null;
+        }
+
+        // Bind (callable[, boundThis], boundArgs) to the delegate handle
+        final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0,
+                Arrays.copyOf(newArgs, firstArgIndex + boundArgs.length));
+        final Class<?> p0Type = type.parameterType(0);
+        final MethodHandle droppingHandle;
+        if (isCall) {
+            // Ignore incoming boundCallable and this
+            droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
+        } else {
+            // Ignore incoming boundCallable
+            droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type);
+        }
+        // Identity guard on boundCallable object
+        final MethodHandle newGuard = Guards.getIdentityGuard(boundCallable);
+        return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
+    }
+}
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
deleted file mode 100644
index 9008547..0000000
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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 General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.linker;
-
-import java.util.Objects;
-import jdk.internal.dynalink.beans.BeansLinker;
-
-/**
- * Represents a Dynalink dynamic method bound to a receiver. Note that objects of this class are just the tuples of
- * a method and a bound this, without any behavior. All the behavior is defined in the {@code BoundDynamicMethodLinker}.
- */
-final class BoundDynamicMethod {
-    private final Object dynamicMethod;
-    private final Object boundThis;
-
-    BoundDynamicMethod(final Object dynamicMethod, final Object boundThis) {
-        assert BeansLinker.isDynamicMethod(dynamicMethod);
-        this.dynamicMethod = dynamicMethod;
-        this.boundThis = boundThis;
-    }
-
-    Object getDynamicMethod() {
-        return dynamicMethod;
-    }
-
-    Object getBoundThis() {
-        return boundThis;
-    }
-
-    @Override
-    public String toString() {
-        return dynamicMethod.toString() + " on " + Objects.toString(boundThis);
-    }
-}
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
deleted file mode 100644
index 67e2983..0000000
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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 General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime.linker;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import jdk.internal.dynalink.CallSiteDescriptor;
-import jdk.internal.dynalink.beans.BeansLinker;
-import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.internal.dynalink.linker.LinkerServices;
-import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
-import jdk.internal.dynalink.support.Guards;
-
-/**
- * Links {@code BoundDynamicMethod} objects. Passes through to Dynalink's BeansLinker for linking a dynamic method
- * (they only respond to "dyn:call"), and modifies the returned invocation to deal with the receiver binding.
- */
-final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
-    @Override
-    public boolean canLinkType(final Class<?> type) {
-        return type == BoundDynamicMethod.class;
-    }
-
-    @Override
-    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
-        final Object objBoundDynamicMethod = linkRequest.getReceiver();
-        if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) {
-            return null;
-        }
-
-        final BoundDynamicMethod boundDynamicMethod = (BoundDynamicMethod)objBoundDynamicMethod;
-        final Object dynamicMethod = boundDynamicMethod.getDynamicMethod();
-        final Object boundThis = boundDynamicMethod.getBoundThis();
-
-        // Replace arguments (boundDynamicMethod, this, ...) => (dynamicMethod, boundThis, ...) when delegating to
-        // BeansLinker
-        final Object[] args = linkRequest.getArguments();
-        args[0] = dynamicMethod;
-        args[1] = boundThis;
-
-        // Use R(T0, T1, ...) => R(dynamicMethod.class, boundThis.class, ...) call site type when delegating to
-        // BeansLinker.
-        final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
-        final MethodType type = descriptor.getMethodType();
-        final Class<?> dynamicMethodClass = dynamicMethod.getClass();
-        final CallSiteDescriptor newDescriptor = descriptor.changeMethodType(
-                type.changeParameterType(0, dynamicMethodClass).changeParameterType(1, boundThis.getClass()));
-
-        // Delegate to BeansLinker
-        final GuardedInvocation inv = NashornBeansLinker.getGuardedInvocation(BeansLinker.getLinkerForClass(dynamicMethodClass),
-                linkRequest.replaceArguments(newDescriptor, args), linkerServices);
-        if(inv == null) {
-            return null;
-        }
-
-        // Bind (dynamicMethod, boundThis) to the handle
-        final MethodHandle boundHandle = MethodHandles.insertArguments(inv.getInvocation(), 0, dynamicMethod, boundThis);
-        final Class<?> p0Type = type.parameterType(0);
-        // Ignore incoming (boundDynamicMethod, this)
-        final MethodHandle droppingHandle = MethodHandles.dropArguments(boundHandle, 0, p0Type, type.parameterType(1));
-        // Identity guard on boundDynamicMethod object
-        final MethodHandle newGuard = Guards.getIdentityGuard(boundDynamicMethod);
-
-        return inv.replaceMethods(droppingHandle, newGuard.asType(newGuard.type().changeParameterType(0, p0Type)));
-    }
-}
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
index fa43e4c..60f639a 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
@@ -45,7 +45,15 @@
  * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects.
  */
 final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
-    private static final ClassLoader myLoader = BrowserJSObjectLinker.class.getClassLoader();
+    private static ClassLoader extLoader;
+    static {
+        extLoader = BrowserJSObjectLinker.class.getClassLoader();
+        // in case nashorn is loaded as bootstrap!
+        if (extLoader == null) {
+            extLoader = ClassLoader.getSystemClassLoader().getParent();
+        }
+    }
+
     private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject";
     // not final because this is lazily initialized
     // when we hit a subclass for the first time.
@@ -69,7 +77,7 @@
         // check if this class is a subclass of JSObject
         Class<?> clazz = type;
         while (clazz != null) {
-            if (clazz.getClassLoader() == myLoader &&
+            if (clazz.getClassLoader() == extLoader &&
                 clazz.getName().equals(JSOBJECT_CLASS)) {
                 jsObjectClass = clazz;
                 return true;
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
index 7700497..df8c61a 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
@@ -104,7 +104,7 @@
                     // SecurityException for nashorn's classes!. For adapter's to work, we
                     // should be able to refer to the few classes it needs in its implementation.
                     if(VISIBLE_INTERNAL_CLASS_NAMES.contains(name)) {
-                        return myLoader.loadClass(name);
+                        return myLoader != null? myLoader.loadClass(name) : Class.forName(name, false, myLoader);
                     }
                     throw se;
                 }
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
index 5fc93cb..9aeefd7 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
@@ -165,7 +165,7 @@
      */
     @SuppressWarnings("unused")
     private static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
-        return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindDynamicMethod(dynamicMethod, boundThis);
+        return dynamicMethod == null ? ScriptRuntime.UNDEFINED : Bootstrap.bindCallable(dynamicMethod, boundThis, null);
     }
 
     /**
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties
index 3a161c8..119277d 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -82,7 +82,7 @@
 type.error.not.a.file={0} is not a File
 type.error.not.a.numeric.array={0} is not a numeric array
 type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
-type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
+type.error.not.an.arraybuffer.in.dataview=First argument to DataView constructor must be an ArrayBuffer
 type.error.no.reflection.with.classfilter=Java reflection not supported when class filter is present
 
 # operations not permitted on undefined
@@ -116,6 +116,7 @@
 type.error.cannot.convert.to.interface=object {0} cannot be converted to {1} due to "{2}"
 type.error.array.reduce.invalid.init=invalid initialValue for Array.prototype.reduce
 type.error.array.reduceright.invalid.init=invalid initialValue for Array.prototype.reduceRight
+type.error.assign.constant=Assignment to constant "{0}"
 type.error.cannot.get.default.string=Cannot get default string value
 type.error.cannot.get.default.number=Cannot get default number value
 type.error.cant.apply.with.to.null=Cannot apply "with" to null
@@ -166,6 +167,7 @@
 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
 syntax.error.redeclare.variable=Variable "{0}" has already been declared
 syntax.error.assign.constant=Assignment to constant "{0}"
+syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
 
 io.error.cant.write=cannot write "{0}"
 config.error.no.dest=no destination directory supplied
diff --git a/test/script/basic/JDK-8049407-big-endian.js b/test/script/basic/JDK-8049407-big-endian.js
new file mode 100644
index 0000000..323c454
--- /dev/null
+++ b/test/script/basic/JDK-8049407-big-endian.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @test
+ * @run
+ * @bigendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "JDK-8049407-payload.js");
diff --git a/test/script/basic/JDK-8049407-big-endian.js.EXPECTED b/test/script/basic/JDK-8049407-big-endian.js.EXPECTED
new file mode 100644
index 0000000..c508d53
--- /dev/null
+++ b/test/script/basic/JDK-8049407-big-endian.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/test/script/basic/JDK-8049407-payload.js b/test/script/basic/JDK-8049407-payload.js
new file mode 100644
index 0000000..467d4bb
--- /dev/null
+++ b/test/script/basic/JDK-8049407-payload.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @subtest
+ * @run
+ */
+
+var littleEndian = (function() {
+	var buffer = new ArrayBuffer(2);
+	new DataView(buffer).setInt16(0, 256, true);
+	return new Int16Array(buffer)[0] === 256;
+    })();
+
+print(littleEndian);
diff --git a/test/script/basic/JDK-8049407.js b/test/script/basic/JDK-8049407.js
new file mode 100644
index 0000000..4bfcd26
--- /dev/null
+++ b/test/script/basic/JDK-8049407.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Verify DataView behavior with little/big endian
+ *
+ * @test
+ * @run
+ * @littleendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "JDK-8049407-payload.js");
diff --git a/test/script/basic/JDK-8049407.js.EXPECTED b/test/script/basic/JDK-8049407.js.EXPECTED
new file mode 100644
index 0000000..27ba77d
--- /dev/null
+++ b/test/script/basic/JDK-8049407.js.EXPECTED
@@ -0,0 +1 @@
+true
diff --git a/test/script/basic/JDK-8051778.js b/test/script/basic/JDK-8051778.js
new file mode 100644
index 0000000..2d8d788
--- /dev/null
+++ b/test/script/basic/JDK-8051778.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8051778: support bind on all Nashorn callables
+ *
+ * @test
+ * @run
+ */
+
+var bind = Function.prototype.bind;
+
+// Bind a POJO method
+var l = new java.util.ArrayList();
+var l_add_foo = bind.call(l.add, l, "foo");
+l_add_foo();
+print("l=" + l);
+
+// Bind a BoundCallable
+var l_add = bind.call(l.add, l);
+var l_add_foo2 = bind.call(l_add, null, "foo2");
+l_add_foo2();
+print("l=" + l);
+
+// Bind a POJO method retrieved from one instance to a different but 
+// compatible instance.
+var l2 = new java.util.ArrayList();
+var l2_size = bind.call(l.size, l2);
+print("l2_size()=" + l2_size());
+
+// Bind a Java type object (used as a constructor).
+var construct_two = bind.call(java.lang.Integer, null, 2);
+print("Bound Integer(2) constructor: " + new construct_two())
+
+// Bind a @FunctionalInterface proxying to an object literal. NOTE: the 
+// expected value of this.a is always "original" and never "bound". This
+// might seem counterintuitive, but we are not binding the apply()
+// function of the object literal that defines the BiFunction behaviour,
+// we are binding the SAM proxy object instead, and it is always
+// forwarding to the apply() function with "this" set to the object
+// literal. Basically, binding "this" for SAM proxies is useless; only
+// binding arguments makes sense.
+var f1 = new java.util.function.BiFunction() {
+    apply: function(x, y) {
+        return "BiFunction with literal: " + this.a + ", " + x + ", " + y;
+    },
+    a: "unbound"
+};
+print((bind.call(f1, {a: "bound"}))(1, 2))
+print((bind.call(f1, {a: "bound"}, 3))(4))
+print((bind.call(f1, {a: "bound"}, 5, 6))())
+
+// Bind a @FunctionalInterface proxying to a function. With the same 
+// reasoning as above (binding the proxy vs. binding the JS function), 
+// the value of this.a will always be undefined, and never "bound".
+var f2 = new java.util.function.BiFunction(
+    function(x, y) {
+        return "BiFunction with function: " + this.a + ", " + x + ", " + y;
+    }
+);
+print((bind.call(f2, {a: "bound"}))(7, 8))
+print((bind.call(f2, {a: "bound"}, 9))(10))
+print((bind.call(f2, {a: "bound"}, 11, 12))())
diff --git a/test/script/basic/JDK-8051778.js.EXPECTED b/test/script/basic/JDK-8051778.js.EXPECTED
new file mode 100644
index 0000000..4ba3e28
--- /dev/null
+++ b/test/script/basic/JDK-8051778.js.EXPECTED
@@ -0,0 +1,10 @@
+l=[foo]
+l=[foo, foo2]
+l2_size()=0
+Bound Integer(2) constructor: 2
+BiFunction with literal: unbound, 1, 2
+BiFunction with literal: unbound, 3, 4
+BiFunction with literal: unbound, 5, 6
+BiFunction with function: undefined, 7, 8
+BiFunction with function: undefined, 9, 10
+BiFunction with function: undefined, 11, 12
diff --git a/test/script/basic/JDK-8066214.js b/test/script/basic/JDK-8066214.js
new file mode 100644
index 0000000..fbf9af3
--- /dev/null
+++ b/test/script/basic/JDK-8066214.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066214: Fuzzing bug: Object.prototype.toLocaleString(0)
+ *
+ * @test
+ * @run
+ */
+
+function test(func) {
+    print(func.call(0));
+    print(func.call("abc"));
+    print(func.call(true));
+    try {
+        print(func.call(undefined));
+    } catch (e) {
+        print(e);
+    }
+    try {
+        print(func.call(null));
+    } catch (e) {
+        print(e);
+    }
+}
+
+test(Object.prototype.toLocaleString);
+test(Object.prototype.toString);
+test(Object.prototype.valueOf);
diff --git a/test/script/basic/JDK-8066214.js.EXPECTED b/test/script/basic/JDK-8066214.js.EXPECTED
new file mode 100644
index 0000000..baf23ea
--- /dev/null
+++ b/test/script/basic/JDK-8066214.js.EXPECTED
@@ -0,0 +1,15 @@
+0
+abc
+true
+TypeError: undefined is not an Object
+TypeError: null is not an Object
+[object Number]
+[object String]
+[object Boolean]
+[object Undefined]
+[object Null]
+0
+abc
+true
+TypeError: undefined is not an Object
+TypeError: null is not an Object
diff --git a/test/script/basic/JDK-8066222.js b/test/script/basic/JDK-8066222.js
new file mode 100644
index 0000000..b5a0b8d
--- /dev/null
+++ b/test/script/basic/JDK-8066222.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066222: too strong assertion on function expression names
+ *
+ * @test
+ * @run
+ */
+
+// Has to print "SUCCESS"
+(function x (x){print(x)})("SUCCESS");
+
+// Has to print "undefined" and "1", not the function source in any case.
+(function x(){print(x); var x=1; print(x)})();
diff --git a/test/script/basic/JDK-8066222.js.EXPECTED b/test/script/basic/JDK-8066222.js.EXPECTED
new file mode 100644
index 0000000..5dad0b6
--- /dev/null
+++ b/test/script/basic/JDK-8066222.js.EXPECTED
@@ -0,0 +1,3 @@
+SUCCESS
+undefined
+1
diff --git a/test/script/basic/JDK-8066232.js b/test/script/basic/JDK-8066232.js
new file mode 100644
index 0000000..cbd481b
--- /dev/null
+++ b/test/script/basic/JDK-8066232.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8066232: problem with conditional catch compilation
+ *
+ * @test
+ * @run
+ */
+
+(function () { 
+    try {
+        x;
+    } catch(e if 1) {
+    }
+})()
+
+print("SUCCESS");
diff --git a/test/script/basic/JDK-8066232.js.EXPECTED b/test/script/basic/JDK-8066232.js.EXPECTED
new file mode 100644
index 0000000..ff43ca4
--- /dev/null
+++ b/test/script/basic/JDK-8066232.js.EXPECTED
@@ -0,0 +1 @@
+SUCCESS
diff --git a/test/script/basic/JDK-8066238.js b/test/script/basic/JDK-8066238.js
new file mode 100644
index 0000000..3a7ec89
--- /dev/null
+++ b/test/script/basic/JDK-8066238.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Parser should not crash on invalid property function bodies.
+ *
+ * @test
+ * @run
+ */
+try {
+    eval("function f() { L: ({ set prop(){0 = null} }); }");
+} catch (e) {
+    if (!(e instanceof ReferenceError)) {
+        throw e;
+    }
+}
+try {
+    eval("function g() { do ; while({ get x()1-- }); }");
+} catch (e) {
+    if (!(e instanceof ReferenceError)) {
+        throw e;
+    }
+}
diff --git a/test/script/basic/NASHORN-377-big-endian.js b/test/script/basic/NASHORN-377-big-endian.js
new file mode 100644
index 0000000..30f0cc3
--- /dev/null
+++ b/test/script/basic/NASHORN-377-big-endian.js
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * NASHORN-377: Typed arrays.
+ *
+ * @test
+ * @run
+ * @bigendian
+ */
+
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "NASHORN-377-payload.js");
diff --git a/test/script/basic/NASHORN-377-big-endian.js.EXPECTED b/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
new file mode 100644
index 0000000..ed3f19a
--- /dev/null
+++ b/test/script/basic/NASHORN-377-big-endian.js.EXPECTED
@@ -0,0 +1,34 @@
+8 8 true undefined
+[object ArrayBuffer] [object ArrayBuffer] [object Int8Array]
+0 8 8 1
+0 8 8 1
+0 8 8 1
+0 8 4 2
+0 8 4 2
+0 8 2 4
+0 8 2 4
+0 8 2 4
+0 8 1 8
+7071727374-807677 7071727374807677
+727374-807677 2 6
+72737480 2 4
+71727374 1 4
+717273748076
+7071727374807677 1886483059 1954575991
+70717273-1020305 1886483059 -16909061
+70717273fefdfcfb 1886483059 4278058235
+40490fdafefdfcfb 2
+400921fb4d12d84a 1
+400921fb4d12d84a 1074340347 1293080650
+00000000400921fb4d12d84a
+400921fb4d12-27b6 400921fb4d12d84a
+00-100804d12-27b6 ffff00804d12d84a
+0 1 2 3 4 5 6 7
+0102030405060708
+subarray(2,4)=0304 subarray(-6,-4)=0304
+010203040506
+03040506 0405
+0102030405060708090a0b0c0d0e0f10
+slice(4,8)=05060708 slice(-8,-4)=090a0b0c
+0102030405060708090a0b0c
+060708090a0b
diff --git a/test/script/basic/NASHORN-377-payload.js b/test/script/basic/NASHORN-377-payload.js
new file mode 100644
index 0000000..b47fb7c
--- /dev/null
+++ b/test/script/basic/NASHORN-377-payload.js
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * NASHORN-377: Typed arrays. Payload for litte and big endian platforms.
+ *
+ * @subtest
+ * @run
+ */
+
+var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
+
+//---------------------------------------------------------------------------
+// utility functions
+//---------------------------------------------------------------------------
+function tohex(d, w) {
+  var hex = Number(d).toString(16);
+  var pad = (w ? w : 8) - hex.length;
+  hex = "00000000".substr(0, pad) + hex;
+  return hex;
+}
+
+function arrstr(a, n, w) {
+  var s = "";
+  if (typeof n == "undefined") n = a.length;
+  if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
+  for (var i = 0; i < n; i++) {
+    s += tohex(a[i], w);
+  }
+  return s;
+}
+function bufstr(b) {
+  if (b.buffer !== undefined) {
+    b = b.buffer;
+  }
+  return arrstr(new Uint8Array(b));
+}
+
+function assertFail(f) {
+  try {
+    f();
+  } catch (e) {
+    //print(e);
+    return;
+  }
+  throw "assertion failed: expected exception";
+}
+
+function assertTrue(f) {
+  if (f() !== true) throw "assertion failed: " + f;
+}
+
+function isUndefined(x) {
+  return typeof x === "undefined";
+}
+
+function fillArray(a, start) {
+  if (typeof start == "undefined") start = 1;
+  for (var i = 0; i < a.length; i++) {
+    a[i] = i + start;
+  }
+  return a;
+}
+
+//---------------------------------------------------------------------------
+// tests
+//---------------------------------------------------------------------------
+(function() {
+  var b = new ArrayBuffer(8);
+  var i8 = new Int8Array(b);
+  print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
+  print(b, i8.buffer, i8);
+})();
+
+(function test_attributes() {
+  var b = new ArrayBuffer(8);
+  for (var i in types) {
+    var x = new types[i](b);
+    print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
+    assertTrue(function(){ return x.constructor === types[i] });
+  }
+})();
+
+(function() {
+  var b = new ArrayBuffer(8);
+  var i8 = new Int8Array(b);
+  fillArray(i8, 0x70);
+
+  var i8_2 = new Int8Array(b, 2);
+  var i8_2_4 = new Uint8Array(b, 2, 4);
+
+  i8_2_4[3] = 0x80;
+
+  print(arrstr(i8, 8, 2)  + " " + bufstr(i8));
+  print(arrstr(i8_2, 6)   + " " + i8_2.byteOffset   + " " + i8_2.byteLength);
+  print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
+
+  var i8_1_5 = i8.subarray(1, 5);
+  i8_2_4.subarray(1, 5);
+  print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
+
+  print(bufstr(b.slice(1,7)));
+})();
+
+(function() {
+  var b = new ArrayBuffer(8);
+  fillArray(new Int8Array(b), 0x70);
+  new Int8Array(b)[5] = 0x80;
+
+  var i32 = new Int32Array(b);
+  var u32 = new Uint32Array(b);
+  print(arrstr(i32), i32[0], i32[1]);
+  i32[1] = 0xfefdfcfb;
+  print(arrstr(i32), i32[0], i32[1]);
+  print(arrstr(u32), u32[0], u32[1]);
+
+  var pi = 3.1415926;
+  var f32 = new Float32Array(b);
+  var f64 = new Float64Array(b);
+  f32[0] = pi;
+  print(bufstr(b), f32.length);
+  f64[0] = pi;
+  print(bufstr(b), f64.length);
+  print(arrstr(u32), u32[0], u32[1]);
+
+  var d = new Int32Array(3);
+  d.set(i32,1);
+  print(bufstr(d));
+
+  var s = new Int16Array(b);
+  var t = new Uint16Array(b);
+  print(arrstr(s), arrstr(t));
+  s[0] = -1; s[1] = 0x80;
+  print(arrstr(s), arrstr(t));
+})();
+
+(function enumerate_properties() {
+  var i8 = new Int8Array(new ArrayBuffer(8));
+  var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
+})();
+
+// check that ScriptObject fallback is still working
+// DISABLED because correct behavior is unclear
+(function() {
+  // NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
+  var z = new Uint8Array(4);
+  z["asdf"] = "asdf"; print(z["asdf"]);
+  z[0x100000000] = "asdf"; print(z[0x100000000]);
+  z[-1] = "asdf"; print(z[-1]);
+
+  // v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
+  z[0xf0000000] = "asdf"; print(z[0xf0000000]);
+  z[0xffffffff] = "asdf"; print(z[0xffffffff]);
+  z[0x70000000] = "asdf"; print(z[0x70000000]);
+
+  // this will work in firefox and nashorn (not in v8).
+  Uint8Array.prototype[4] = "asdf"; print(z[4]);
+});
+
+(function test_exceptions() {
+  assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
+  assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
+  assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
+  assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
+})();
+
+(function test_subarray() {
+  var x = fillArray(new Int8Array(8));
+  print(arrstr(x));
+  print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
+  print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
+  assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
+  print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
+})();
+
+(function test_slice() {
+  var b = new ArrayBuffer(16);
+  fillArray(new Int8Array(b));
+  print(bufstr(b));
+  print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
+  print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
+  assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
+  print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
+})();
+
+(function test_clamped() {
+  var a = new Uint8ClampedArray(10);
+  a[0] = -17;       // clamped to 0
+  a[1] = 4711;      // clamped to 255
+  a[2] = 17.5;      // clamped to 18
+  a[3] = 16.5;      // clamped to 16
+  a[4] = 255.9;     // clamped to 255
+  a[5] = Infinity;  // clamped to 255
+  a[6] = -Infinity; // clamped to 0
+  a[7] = NaN;       // 0
+  assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
+})();
+
+(function test_out_of_bounds() {
+  var a = new Int32Array(10);
+  a[10] = 10;
+  a[100] = 100;
+  a[1000] = 1000;
+  assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
+})();
+
diff --git a/test/script/basic/NASHORN-377.js b/test/script/basic/NASHORN-377.js
index 968e46e..3484223 100644
--- a/test/script/basic/NASHORN-377.js
+++ b/test/script/basic/NASHORN-377.js
@@ -26,201 +26,8 @@
  *
  * @test
  * @run
+ * @littleendian
  */
 
-var types = [Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];
-
-//---------------------------------------------------------------------------
-// utility functions
-//---------------------------------------------------------------------------
-function tohex(d, w) {
-  var hex = Number(d).toString(16);
-  var pad = (w ? w : 8) - hex.length;
-  hex = "00000000".substr(0, pad) + hex;
-  return hex;
-}
-
-function arrstr(a, n, w) {
-  var s = "";
-  if (typeof n == "undefined") n = a.length;
-  if (typeof w == "undefined") w = a.constructor.BYTES_PER_ELEMENT * 2;
-  for (var i = 0; i < n; i++) {
-    s += tohex(a[i], w);
-  }
-  return s;
-}
-function bufstr(b) {
-  if (b.buffer !== undefined) {
-    b = b.buffer;
-  }
-  return arrstr(new Uint8Array(b));
-}
-
-function assertFail(f) {
-  try {
-    f();
-  } catch (e) {
-    //print(e);
-    return;
-  }
-  throw "assertion failed: expected exception";
-}
-
-function assertTrue(f) {
-  if (f() !== true) throw "assertion failed: " + f;
-}
-
-function isUndefined(x) {
-  return typeof x === "undefined";
-}
-
-function fillArray(a, start) {
-  if (typeof start == "undefined") start = 1;
-  for (var i = 0; i < a.length; i++) {
-    a[i] = i + start;
-  }
-  return a;
-}
-
-//---------------------------------------------------------------------------
-// tests
-//---------------------------------------------------------------------------
-(function() {
-  var b = new ArrayBuffer(8);
-  var i8 = new Int8Array(b);
-  print(i8.buffer.byteLength, b.byteLength, i8.buffer === b, b.length);
-  print(b, i8.buffer, i8);
-})();
-
-(function test_attributes() {
-  var b = new ArrayBuffer(8);
-  for (var i in types) {
-    var x = new types[i](b);
-    print(x.byteOffset, x.byteLength, x.length, x.constructor.BYTES_PER_ELEMENT);
-    assertTrue(function(){ return x.constructor === types[i] });
-  }
-})();
-
-(function() {
-  var b = new ArrayBuffer(8);
-  var i8 = new Int8Array(b);
-  fillArray(i8, 0x70);
-
-  var i8_2 = new Int8Array(b, 2);
-  var i8_2_4 = new Uint8Array(b, 2, 4);
-
-  i8_2_4[3] = 0x80;
-
-  print(arrstr(i8, 8, 2)  + " " + bufstr(i8));
-  print(arrstr(i8_2, 6)   + " " + i8_2.byteOffset   + " " + i8_2.byteLength);
-  print(arrstr(i8_2_4, 4) + " " + i8_2_4.byteOffset + " " + i8_2_4.byteLength);
-
-  var i8_1_5 = i8.subarray(1, 5);
-  i8_2_4.subarray(1, 5);
-  print(arrstr(i8_1_5, 4) + " " + i8_1_5.byteOffset + " " + i8_1_5.byteLength);
-
-  print(bufstr(b.slice(1,7)));
-})();
-
-(function() {
-  var b = new ArrayBuffer(8);
-  fillArray(new Int8Array(b), 0x70);
-  new Int8Array(b)[5] = 0x80;
-
-  var i32 = new Int32Array(b);
-  var u32 = new Uint32Array(b);
-  print(arrstr(i32), i32[0], i32[1]);
-  i32[1] = 0xfefdfcfb;
-  print(arrstr(i32), i32[0], i32[1]);
-  print(arrstr(u32), u32[0], u32[1]);
-
-  var pi = 3.1415926;
-  var f32 = new Float32Array(b);
-  var f64 = new Float64Array(b);
-  f32[0] = pi;
-  print(bufstr(b), f32.length);
-  f64[0] = pi;
-  print(bufstr(b), f64.length);
-  print(arrstr(u32), u32[0], u32[1]);
-
-  var d = new Int32Array(3);
-  d.set(i32,1);
-  print(bufstr(d));
-
-  var s = new Int16Array(b);
-  var t = new Uint16Array(b);
-  print(arrstr(s), arrstr(t));
-  s[0] = -1; s[1] = 0x80;
-  print(arrstr(s), arrstr(t));
-})();
-
-(function enumerate_properties() {
-  var i8 = new Int8Array(new ArrayBuffer(8));
-  var s = ""; for (var i in i8) { s += i + " "; } print(s.trim());
-})();
-
-// check that ScriptObject fallback is still working
-// DISABLED because correct behavior is unclear
-(function() {
-  // NB: firefox will never set any out-of-bounds or non-array values although it does get both from prototype.
-  var z = new Uint8Array(4);
-  z["asdf"] = "asdf"; print(z["asdf"]);
-  z[0x100000000] = "asdf"; print(z[0x100000000]);
-  z[-1] = "asdf"; print(z[-1]);
-
-  // v8 and nashorn disagree on out-of-bounds uint32 indices: v8 won't go to the prototype.
-  z[0xf0000000] = "asdf"; print(z[0xf0000000]);
-  z[0xffffffff] = "asdf"; print(z[0xffffffff]);
-  z[0x70000000] = "asdf"; print(z[0x70000000]);
-
-  // this will work in firefox and nashorn (not in v8).
-  Uint8Array.prototype[4] = "asdf"; print(z[4]);
-});
-
-(function test_exceptions() {
-  assertFail(function() { new Int32Array(new ArrayBuffer(7)); });
-  assertFail(function() { new Int32Array(new ArrayBuffer(8), 0, 4); });
-  assertFail(function() { new Int32Array(new ArrayBuffer(8),-1, 2); });
-  assertFail(function() { new Int32Array(new ArrayBuffer(8), 0,-1); });
-})();
-
-(function test_subarray() {
-  var x = fillArray(new Int8Array(8));
-  print(arrstr(x));
-  print("subarray(2,4)=" + arrstr(x.subarray(2, 4)), "subarray(-6,-4)=" + arrstr(x.subarray(-6, -4))); // negative index refers from the end of the array
-  print(arrstr(x.subarray(-10, -2))); // negative index clamped to 0
-  assertTrue(function(){ return arrstr(x.subarray(6, 4)) === ""; }); // negative length clamped to 0
-  print(arrstr(x.subarray(1,-1).subarray(1,-1)), arrstr(x.subarray(1,-1).subarray(1,-1).subarray(1,-1))); // subarray of subarray
-})();
-
-(function test_slice() {
-  var b = new ArrayBuffer(16);
-  fillArray(new Int8Array(b));
-  print(bufstr(b));
-  print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
-  print(bufstr(b.slice(-20, -4))); // negative index clamped to 0
-  assertTrue(function(){ return bufstr(b.slice(8, 4)) === ""; }); // negative length clamped to 0
-  print(arrstr(new Int16Array(b.slice(1,-1).slice(2,-1).slice(1,-2).slice(1,-1)))); // slice of slice
-})();
-
-(function test_clamped() {
-  var a = new Uint8ClampedArray(10);
-  a[0] = -17;       // clamped to 0
-  a[1] = 4711;      // clamped to 255
-  a[2] = 17.5;      // clamped to 18
-  a[3] = 16.5;      // clamped to 16
-  a[4] = 255.9;     // clamped to 255
-  a[5] = Infinity;  // clamped to 255
-  a[6] = -Infinity; // clamped to 0
-  a[7] = NaN;       // 0
-  assertTrue(function(){ return a[0] === 0 && a[1] === 255 && a[2] === 18 && a[3] === 16 && a[4] === 255 && a[5] === 255 && a[6] === 0 && a[7] === 0; });
-})();
-
-(function test_out_of_bounds() {
-  var a = new Int32Array(10);
-  a[10] = 10;
-  a[100] = 100;
-  a[1000] = 1000;
-  assertTrue(function(){ return isUndefined(a[10]) && isUndefined(a[11]) && isUndefined(a[100]) && isUndefined(a[123]) && isUndefined(a[1000]); });
-})();
-
+var dir = typeof(__DIR__) == 'undefined' ? "test/script/basic/" : __DIR__;
+load(dir + "NASHORN-377-payload.js");
diff --git a/test/script/basic/es6/const-redeclare-extra.js.EXPECTED b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED
index 754a75c..06af782 100644
--- a/test/script/basic/es6/const-redeclare-extra.js.EXPECTED
+++ b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED
@@ -1,9 +1,9 @@
 SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
     var x = {};
         ^
-SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared
-    var x = 2;
-        ^
-SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared
-    function x () {}
-             ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
+    const x = {};
+          ^
+SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
+    const x = 5;
+          ^
diff --git a/test/script/basic/es6/for-let.js b/test/script/basic/es6/for-let.js
index 949b348..848dc3c 100644
--- a/test/script/basic/es6/for-let.js
+++ b/test/script/basic/es6/for-let.js
@@ -39,3 +39,40 @@
 } catch (e) {
     print(e);
 }
+
+let a = [];
+
+for (let i = 0; i < 10; i++) {
+    a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+a = [];
+
+for (let i = 0; i < 10; i++) {
+    if (i == 5) {
+        i = "foo";
+    }
+    a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
+
+try {
+    print(i);
+} catch (e) {
+    print(e);
+}
+
+a = [];
+
+for (let i = 0; i < 20; i++) {
+    if (i % 2 == 1) {
+        i += 2;
+        continue;
+    }
+    a.push(function() { print(i); });
+}
+
+a.forEach(function(f) { f(); });
diff --git a/test/script/basic/es6/for-let.js.EXPECTED b/test/script/basic/es6/for-let.js.EXPECTED
index 4c1ebad..21787ad 100644
--- a/test/script/basic/es6/for-let.js.EXPECTED
+++ b/test/script/basic/es6/for-let.js.EXPECTED
@@ -9,3 +9,25 @@
 8
 9
 ReferenceError: "i" is not defined
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+0
+1
+2
+3
+4
+foo
+ReferenceError: "i" is not defined
+0
+4
+8
+12
+16
diff --git a/test/script/basic/es6/let-const-statement-context.js b/test/script/basic/es6/let-const-statement-context.js
new file mode 100644
index 0000000..3e66237
--- /dev/null
+++ b/test/script/basic/es6/let-const-statement-context.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057980: let & const: remaining issues with lexical scoping
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function tryEval(s) {
+    try {
+        eval(s);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"));
+    }
+}
+
+tryEval('if (true) let x = 1;');
+tryEval('if (true) const x = 1;');
+tryEval('while (true) let x = 1;');
+tryEval('while (true) const x = 1;');
+tryEval('for (;;) let x = 1;');
+tryEval('for (;;) const x = 1;');
+tryEval('do let x = 1; while (true);');
+tryEval('do const x = 1; while (true);');
+tryEval('with (y) const x = 1;');
+tryEval('with (y) let x = 1;');
diff --git a/test/script/basic/es6/let-const-statement-context.js.EXPECTED b/test/script/basic/es6/let-const-statement-context.js.EXPECTED
new file mode 100644
index 0000000..1b73e4c
--- /dev/null
+++ b/test/script/basic/es6/let-const-statement-context.js.EXPECTED
@@ -0,0 +1,30 @@
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found let declaration
+if (true) let x = 1;
+          ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:10 Expected statement but found const declaration
+if (true) const x = 1;
+          ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found let declaration
+while (true) let x = 1;
+             ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:13 Expected statement but found const declaration
+while (true) const x = 1;
+             ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
+for (;;) let x = 1;
+         ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
+for (;;) const x = 1;
+         ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found let declaration
+do let x = 1; while (true);
+   ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:3 Expected statement but found const declaration
+do const x = 1; while (true);
+   ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found const declaration
+with (y) const x = 1;
+         ^
+SyntaxError: test/script/basic/es6/let-const-statement-context.js#34:8<eval>:1:9 Expected statement but found let declaration
+with (y) let x = 1;
+         ^
diff --git a/test/script/basic/es6/let-const-switch.js b/test/script/basic/es6/let-const-switch.js
new file mode 100644
index 0000000..8a538b8
--- /dev/null
+++ b/test/script/basic/es6/let-const-switch.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057980: let & const: remaining issues with lexical scoping
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function tryEval(s) {
+    try {
+        eval(s);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"));
+    }
+}
+
+tryEval('var x = 0; switch (x) { case 0: { let   x = 1; print(x); } case 1: { let   x = 2; print(x); }} print(x);');
+tryEval('var x = 0; switch (x) { case 0: { const x = 1; print(x); } case 1: { const x = 2; print(x); }} print(x);');
+
+// TODO: the following should not throw
+tryEval('switch (x) { case 0: let x = 1; }');
+tryEval('switch (x) { case 0: const x = 1; }');
diff --git a/test/script/basic/es6/let-const-switch.js.EXPECTED b/test/script/basic/es6/let-const-switch.js.EXPECTED
new file mode 100644
index 0000000..90309bf
--- /dev/null
+++ b/test/script/basic/es6/let-const-switch.js.EXPECTED
@@ -0,0 +1,12 @@
+1
+2
+0
+1
+2
+0
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:25 Unsupported let declaration in unprotected switch statement
+switch (x) { case 0: let x = 1; }
+                         ^
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:27 Unsupported const declaration in unprotected switch statement
+switch (x) { case 0: const x = 1; }
+                           ^
diff --git a/test/script/basic/es6/let-load.js b/test/script/basic/es6/let-load.js
index b4c2946..ff8f4e1 100644
--- a/test/script/basic/es6/let-load.js
+++ b/test/script/basic/es6/let-load.js
@@ -26,7 +26,8 @@
  *
  * @test
  * @run
- * @option --language=es6 */
+ * @option --language=es6
+ */
 
 "use strict";
 
@@ -39,17 +40,8 @@
 }
 
 print("imported var: " + a);
-try {
-    print("imported let: " + b);
-} catch (e) {
-    print(e);
-}
-
-try {
-    print("imported const: " + c);
-} catch (e) {
-    print(e);
-}
+print("imported let: " + b);
+print("imported const: " + c);
 
 top();
 
@@ -59,4 +51,10 @@
     print(e);
 }
 
+try {
+    c = "foo";
+} catch (e) {
+    print(e);
+}
+
 
diff --git a/test/script/basic/es6/let-load.js.EXPECTED b/test/script/basic/es6/let-load.js.EXPECTED
index 510da6e..a0b2e09 100644
--- a/test/script/basic/es6/let-load.js.EXPECTED
+++ b/test/script/basic/es6/let-load.js.EXPECTED
@@ -2,7 +2,8 @@
 block function
 print local defs: 20 30
 imported var: 1
-ReferenceError: "b" is not defined
-ReferenceError: "c" is not defined
+imported let: 2
+imported const: 3
 top level function
 ReferenceError: "block" is not defined
+TypeError: Assignment to constant "c"
diff --git a/test/script/basic/es6/let-redeclare-extra.js.EXPECTED b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED
index 5e43b69..e0e1afe 100644
--- a/test/script/basic/es6/let-redeclare-extra.js.EXPECTED
+++ b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED
@@ -4,12 +4,12 @@
 SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
     var x = 2;
         ^
-SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
-    var x = 2;
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
+    let x = undefined;
         ^
 SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
     const x = function (){};
           ^
-SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared
-    function a () {};
-             ^
+SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "a" has already been declared
+    let a = 2;
+        ^
diff --git a/test/script/basic/es6/let_const_closure.js.EXPECTED b/test/script/basic/es6/let_const_closure.js.EXPECTED
index 5a720d8..f49ca4b 100644
--- a/test/script/basic/es6/let_const_closure.js.EXPECTED
+++ b/test/script/basic/es6/let_const_closure.js.EXPECTED
@@ -5,9 +5,9 @@
 test
 test
 test
-3
-3
-3
+0
+1
+2
 0
 1
 2
diff --git a/test/script/basic/es6/lexical-toplevel-def.js b/test/script/basic/es6/lexical-toplevel-def.js
new file mode 100644
index 0000000..c9a44f7
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-def.js
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+var   VAR   = "VAR";
+let   LET   = "LET";
+const CONST = "CONST";
+function FUNC() {}
+this.GLOBAL = "GLOBAL";
diff --git a/test/script/basic/es6/lexical-toplevel-print.js b/test/script/basic/es6/lexical-toplevel-print.js
new file mode 100644
index 0000000..eef030a
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-print.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+print(VAR);
+print(LET);
+print(CONST);
+print(FUNC);
+print(GLOBAL);
+print(this.VAR);
+print(this.LET);   // undefined
+print(this.CONST); // undefined
+print(this.FUNC);
+print(this.GLOBAL);
+print("VAR" in this);
+print("LET" in this);   // false
+print("CONST" in this); // false
+print("FUNC" in this);
+print("GLOBAL" in this);
+
+try {
+    LET   = LET + "LET";
+    CONST = CONST + "CONST";
+} catch (e) {
+    print(String(e).replace(/\\/g, "/"));
+}
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js b/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js
new file mode 100644
index 0000000..bfe7af3
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+function LET() {}
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js
new file mode 100644
index 0000000..6436014
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let Object = "LEXICAL BUILTIN";
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js
new file mode 100644
index 0000000..44c8396
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let FUNC = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js
new file mode 100644
index 0000000..a742fad
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let GLOBAL = "LEXICAL GLOBAL";
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js
new file mode 100644
index 0000000..630741f
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+let VAR = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js b/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js
new file mode 100644
index 0000000..cb4b382
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @subtest
+ */
+
+var LET = 10;
+var SHOULD_NOT_EXIST = 10;
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare.js b/test/script/basic/es6/lexical-toplevel-redeclare.js
new file mode 100644
index 0000000..6a76622
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @test
+ * @run
+ * @option -scripting
+ * @option --language=es6
+ */
+
+load(__DIR__ + "lexical-toplevel-def.js");
+
+var global = this;
+
+function tryIt (code) {
+    try {
+        eval(code)
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"))
+    }
+}
+
+function loadScript(script) {
+    print(script);
+    try {
+        load(__DIR__ + script);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"));
+    }
+    print(VAR);
+    print(LET);
+    print(CONST);
+    print(FUNC);
+    print(GLOBAL);
+    print(global.VAR);
+    print(global.LET);
+    print(global.CONST);
+    print(global.FUNC);
+    print(global.GLOBAL);
+    try {
+        print(SHOULD_NOT_EXIST);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"));
+    }
+    print(global.SHOULD_NOT_EXIST);
+    print(Object);
+    print(global.Object);
+    print();
+}
+
+loadScript("lexical-toplevel-redeclare-var-on-let.js");
+loadScript("lexical-toplevel-redeclare-func-on-let.js");
+loadScript("lexical-toplevel-redeclare-let-on-var.js");
+loadScript("lexical-toplevel-redeclare-let-on-func.js");
+loadScript("lexical-toplevel-redeclare-let-on-builtin.js");
+loadScript("lexical-toplevel-redeclare-let-on-global.js");
diff --git a/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED b/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED
new file mode 100644
index 0000000..d1471c8
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED
@@ -0,0 +1,100 @@
+lexical-toplevel-redeclare-var-on-let.js
+SyntaxError: Variable "LET" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-func-on-let.js
+SyntaxError: Variable "LET" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-var.js
+SyntaxError: Variable "VAR" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-func.js
+SyntaxError: Variable "FUNC" has already been declared
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+function Object() { [native code] }
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-builtin.js
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+LEXICAL BUILTIN
+function Object() { [native code] }
+
+lexical-toplevel-redeclare-let-on-global.js
+VAR
+LET
+CONST
+function FUNC() {}
+LEXICAL GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+ReferenceError: "SHOULD_NOT_EXIST" is not defined
+undefined
+LEXICAL BUILTIN
+function Object() { [native code] }
+
diff --git a/test/script/basic/es6/lexical-toplevel.js b/test/script/basic/es6/lexical-toplevel.js
new file mode 100644
index 0000000..fc272a8
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+load(__DIR__ + "lexical-toplevel-def.js");
+
+load(__DIR__ + "lexical-toplevel-print.js");
+load(__DIR__ + "lexical-toplevel-print.js");
diff --git a/test/script/basic/es6/lexical-toplevel.js.EXPECTED b/test/script/basic/es6/lexical-toplevel.js.EXPECTED
new file mode 100644
index 0000000..7580af4
--- /dev/null
+++ b/test/script/basic/es6/lexical-toplevel.js.EXPECTED
@@ -0,0 +1,32 @@
+VAR
+LET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+true
+false
+false
+true
+true
+TypeError: Assignment to constant "CONST"
+VAR
+LETLET
+CONST
+function FUNC() {}
+GLOBAL
+VAR
+undefined
+undefined
+function FUNC() {}
+GLOBAL
+true
+false
+false
+true
+true
+TypeError: Assignment to constant "CONST"
diff --git a/test/script/nosecurity/JDK-8050964.js b/test/script/nosecurity/JDK-8050964.js
index 39cc1c6..cedec0c 100644
--- a/test/script/nosecurity/JDK-8050964.js
+++ b/test/script/nosecurity/JDK-8050964.js
@@ -53,6 +53,7 @@
 }
 
 // run jdep on nashorn.jar - only summary but print profile info
+$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
 `${jdepsPath} -s -P ${nashornJar.absolutePath}`
 
 // check for "(compact1)" in output from jdep tool
diff --git a/test/script/nosecurity/JDK-8055034.js b/test/script/nosecurity/JDK-8055034.js
index 9e7a430..55a3b03 100644
--- a/test/script/nosecurity/JDK-8055034.js
+++ b/test/script/nosecurity/JDK-8055034.js
@@ -43,7 +43,6 @@
 if (! nashornJar.isAbsolute()) {
     nashornJar = new File(".", nashornJar);
 }
-var nashornJarDir = nashornJar.parentFile.absolutePath;
 
 // we want to use nashorn.jar passed and not the one that comes with JRE
 var jjsCmd = javahome + "/../bin/jjs";
@@ -52,8 +51,9 @@
     jjsCmd = javahome + "/bin/jjs";
     jjsCmd = jjsCmd.toString().replaceAll(/\//g, File.separater);
 }
-jjsCmd += " -J-Xbootclasspath/a:" + nashornJarDir;
+jjsCmd += " -J-Xbootclasspath/p:" + nashornJar;
 
+$ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
 $EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
 
 // $ERR has all interactions including prompts! Just check for error substring.
diff --git a/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java b/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
new file mode 100644
index 0000000..2cd0bf0
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.Test;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Top-level lexical binding tests.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
+ */
+@SuppressWarnings("javadoc")
+public class LexicalBindingTest {
+
+    final static String LANGUAGE_ES6 = "--language=es6";
+    final static int NUMBER_OF_CONTEXTS = 20;
+    final static int MEGAMORPHIC_LOOP_COUNT = 20;
+
+    /**
+     * Test access to global var-declared variables for shared script classes with multiple globals.
+     */
+    @Test
+    public static void megamorphicVarTest() throws ScriptException, InterruptedException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine e = factory.getScriptEngine();
+        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
+        final String sharedScript = "foo";
+
+
+        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+            final ScriptContext context = contexts[i] = new SimpleScriptContext();
+            final Bindings b = e.createBindings();
+            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
+            assertEquals(e.eval("var foo = '" + i + "';", context), null);
+        }
+
+        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+            final ScriptContext context = contexts[i];
+            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
+        }
+    }
+
+    /**
+     * Test access to global lexically declared variables for shared script classes with multiple globals.
+     */
+    @Test
+    public static void megamorphicMultiGlobalLetTest() throws ScriptException, InterruptedException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
+        final String sharedScript = "foo";
+
+
+        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+            final ScriptContext context = contexts[i] = new SimpleScriptContext();
+            final Bindings b = e.createBindings();
+            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
+            assertEquals(e.eval("let foo = '" + i + "';", context), null);
+        }
+
+        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
+            final ScriptContext context = contexts[i];
+            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
+        }
+    }
+
+
+    /**
+     * Test access to global lexically declared variables for shared script classes with single global.
+     */
+    @Test
+    public static void megamorphicSingleGlobalLetTest() throws ScriptException, InterruptedException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+        final String sharedGetterScript = "foo";
+        final String sharedSetterScript = "foo = 1";
+
+        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
+            assertEquals(e.eval(sharedSetterScript), 1);
+            assertEquals(e.eval(sharedGetterScript), 1);
+            assertEquals(e.eval("delete foo; a" + i + " = 1; foo = " + i + ";"), i);
+            assertEquals(e.eval(sharedGetterScript), i);
+        }
+
+        assertEquals(e.eval("let foo = 'foo';"), null);
+        assertEquals(e.eval(sharedGetterScript), "foo");
+        assertEquals(e.eval(sharedSetterScript), 1);
+        assertEquals(e.eval(sharedGetterScript), 1);
+        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
+    }
+
+    /**
+     * Test access to global lexically declared variables for shared script classes with single global.
+     */
+    @Test
+    public static void megamorphicInheritedGlobalLetTest() throws ScriptException, InterruptedException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+        final String sharedGetterScript = "foo";
+        final String sharedSetterScript = "foo = 1";
+
+        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
+            assertEquals(e.eval(sharedSetterScript), 1);
+            assertEquals(e.eval(sharedGetterScript), 1);
+            assertEquals(e.eval("delete foo; a" + i + " = 1; Object.prototype.foo = " + i + ";"), i);
+            assertEquals(e.eval(sharedGetterScript), i);
+        }
+
+        assertEquals(e.eval("let foo = 'foo';"), null);
+        assertEquals(e.eval(sharedGetterScript), "foo");
+        assertEquals(e.eval(sharedSetterScript), 1);
+        assertEquals(e.eval(sharedGetterScript), 1);
+        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
+    }
+
+    /**
+     * Test multi-threaded access to global lexically declared variables for shared script classes with multiple globals.
+     */
+    @Test
+    public static void multiThreadedLetTest() throws ScriptException, InterruptedException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
+        final Bindings b = e.createBindings();
+        final ScriptContext origContext = e.getContext();
+        final ScriptContext newCtxt = new SimpleScriptContext();
+        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+        final String sharedScript = "foo";
+
+        assertEquals(e.eval("let foo = 'original context';", origContext), null);
+        assertEquals(e.eval("let foo = 'new context';", newCtxt), null);
+
+        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+        t1.start();
+        t2.start();
+        t1.join();
+        t2.join();
+
+        assertEquals(e.eval("foo = 'newer context';", newCtxt), "newer context");
+        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+        t3.start();
+        t4.start();
+        t3.join();
+        t4.join();
+
+        assertEquals(e.eval(sharedScript), "original context");
+        assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+    }
+
+    private static class ScriptRunner implements Runnable {
+
+        final ScriptEngine engine;
+        final ScriptContext context;
+        final String source;
+        final Object expected;
+        final int iterations;
+
+        ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
+            this.engine = engine;
+            this.context = context;
+            this.source = source;
+            this.expected = expected;
+            this.iterations = iterations;
+        }
+
+        @Override
+        public void run() {
+            try {
+                for (int i = 0; i < iterations; i++) {
+                    assertEquals(engine.eval(source, context), expected);
+                }
+            } catch (final ScriptException se) {
+                throw new RuntimeException(se);
+            }
+        }
+    }
+}
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
index 851cb46..3f4252b 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
@@ -46,6 +46,7 @@
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.nio.ByteOrder;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.FileVisitOption;
@@ -264,6 +265,12 @@
                     isTest = false;
                     isNotTest = true;
                     break;
+                case "@bigendian":
+                    shouldRun = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
+                    break;
+                case "@littleendian":
+                    shouldRun = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+                    break;
                 case "@runif": {
                     final String prop = scanner.next();
                     if (System.getProperty(prop) != null) {