8057691: Nashorn: let & const declarations are not shared between scripts

Mon, 24 Nov 2014 12:03:15 +0100

author
hannesw
date
Mon, 24 Nov 2014 12:03:15 +0100
changeset 1105
c3a510b73875
parent 1104
c22dd9ae7ff0
child 1106
ac111e4cb1dc

8057691: Nashorn: let & const declarations are not shared between scripts
Reviewed-by: lagergren, attila

src/jdk/nashorn/internal/codegen/AssignSymbols.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/MapCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/parser/Parser.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Property.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
test/script/basic/es6/const-redeclare-extra.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/es6/let-load.js file | annotate | diff | comparison | revisions
test/script/basic/es6/let-load.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/es6/let-redeclare-extra.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-def.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-print.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel.js file | annotate | diff | comparison | revisions
test/script/basic/es6/lexical-toplevel.js.EXPECTED file | annotate | diff | comparison | revisions
test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Fri Nov 21 20:17:02 2014 +0100
     1.2 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java	Mon Nov 24 12:03:15 2014 +0100
     1.3 @@ -356,6 +356,10 @@
     1.4                          throwParserException(ECMAErrors.getMessage("syntax.error.redeclare.variable", name), origin);
     1.5                      } else {
     1.6                          symbol.setHasBeenDeclared();
     1.7 +                        // Set scope flag on top-level block scoped symbols
     1.8 +                        if (function.isProgram() && function.getBody() == block) {
     1.9 +                            symbol.setIsScope();
    1.10 +                        }
    1.11                      }
    1.12                  } else if ((flags & IS_INTERNAL) != 0) {
    1.13                      // Always create a new definition.
    1.14 @@ -540,7 +544,7 @@
    1.15          final int flags;
    1.16          if (varNode.isAnonymousFunctionDeclaration()) {
    1.17              flags = IS_INTERNAL;
    1.18 -        } else if (lc.getCurrentFunction().isProgram()) {
    1.19 +        } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
    1.20              flags = IS_SCOPE;
    1.21          } else {
    1.22              flags = 0;
     2.1 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java	Fri Nov 21 20:17:02 2014 +0100
     2.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java	Mon Nov 24 12:03:15 2014 +0100
     2.3 @@ -152,6 +152,10 @@
     2.4              flags |= Property.NOT_WRITABLE;
     2.5          }
     2.6  
     2.7 +        if (symbol.isBlockScoped()) {
     2.8 +            flags |= Property.IS_LEXICAL_BINDING;
     2.9 +        }
    2.10 +
    2.11          // Mark symbol as needing declaration. Access before declaration will throw a ReferenceError.
    2.12          if (symbol.isBlockScoped() && symbol.isScope()) {
    2.13              flags |= Property.NEEDS_DECLARATION;
     3.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Fri Nov 21 20:17:02 2014 +0100
     3.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Mon Nov 24 12:03:15 2014 +0100
     3.3 @@ -34,6 +34,7 @@
     3.4  import java.io.PrintWriter;
     3.5  import java.lang.invoke.MethodHandle;
     3.6  import java.lang.invoke.MethodHandles;
     3.7 +import java.lang.invoke.MethodType;
     3.8  import java.lang.invoke.SwitchPoint;
     3.9  import java.lang.reflect.Field;
    3.10  import java.util.ArrayList;
    3.11 @@ -44,6 +45,7 @@
    3.12  import java.util.concurrent.ConcurrentHashMap;
    3.13  import javax.script.ScriptContext;
    3.14  import javax.script.ScriptEngine;
    3.15 +import jdk.internal.dynalink.CallSiteDescriptor;
    3.16  import jdk.internal.dynalink.linker.GuardedInvocation;
    3.17  import jdk.internal.dynalink.linker.LinkRequest;
    3.18  import jdk.nashorn.api.scripting.ClassFilter;
    3.19 @@ -54,6 +56,8 @@
    3.20  import jdk.nashorn.internal.objects.annotations.ScriptClass;
    3.21  import jdk.nashorn.internal.runtime.ConsString;
    3.22  import jdk.nashorn.internal.runtime.Context;
    3.23 +import jdk.nashorn.internal.runtime.ECMAErrors;
    3.24 +import jdk.nashorn.internal.runtime.GlobalConstants;
    3.25  import jdk.nashorn.internal.runtime.GlobalFunctions;
    3.26  import jdk.nashorn.internal.runtime.JSType;
    3.27  import jdk.nashorn.internal.runtime.NativeJavaPackage;
    3.28 @@ -69,6 +73,7 @@
    3.29  import jdk.nashorn.internal.runtime.arrays.ArrayData;
    3.30  import jdk.nashorn.internal.runtime.linker.Bootstrap;
    3.31  import jdk.nashorn.internal.runtime.linker.InvokeByName;
    3.32 +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
    3.33  import jdk.nashorn.internal.runtime.regexp.RegExpResult;
    3.34  import jdk.nashorn.internal.scripts.JO;
    3.35  
    3.36 @@ -410,13 +415,14 @@
    3.37      // Used to store the last RegExp result to support deprecated RegExp constructor properties
    3.38      private RegExpResult lastRegExpResult;
    3.39  
    3.40 -    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
    3.41 -    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
    3.42 -    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
    3.43 -    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
    3.44 -    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
    3.45 -    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
    3.46 -    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
    3.47 +    private static final MethodHandle EVAL                 = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
    3.48 +    private static final MethodHandle NO_SUCH_PROPERTY     = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
    3.49 +    private static final MethodHandle PRINT                = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
    3.50 +    private static final MethodHandle PRINTLN              = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
    3.51 +    private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
    3.52 +    private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
    3.53 +    private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
    3.54 +    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
    3.55  
    3.56      // initialized by nasgen
    3.57      private static PropertyMap $nasgenmap$;
    3.58 @@ -429,6 +435,12 @@
    3.59      // current ScriptEngine associated - can be null.
    3.60      private ScriptEngine engine;
    3.61  
    3.62 +    // ES6 global lexical scope.
    3.63 +    private final LexicalScope lexicalScope;
    3.64 +
    3.65 +    // Switchpoint for non-constant global callsites in the presence of ES6 lexical scope.
    3.66 +    private SwitchPoint lexicalScopeSwitchPoint;
    3.67 +
    3.68      /**
    3.69       * Set the current script context
    3.70       * @param scontext script context
    3.71 @@ -466,6 +478,7 @@
    3.72          super(checkAndGetMap(context));
    3.73          this.context = context;
    3.74          this.setIsScope();
    3.75 +        this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
    3.76      }
    3.77  
    3.78      /**
    3.79 @@ -1694,6 +1707,133 @@
    3.80          splitState = state;
    3.81      }
    3.82  
    3.83 +    /**
    3.84 +     * Return the ES6 global scope for lexically declared bindings.
    3.85 +     * @return the ES6 lexical global scope.
    3.86 +     */
    3.87 +    public final ScriptObject getLexicalScope() {
    3.88 +        assert context.getEnv()._es6;
    3.89 +        return lexicalScope;
    3.90 +    }
    3.91 +
    3.92 +    @Override
    3.93 +    public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
    3.94 +        PropertyMap ownMap = getMap();
    3.95 +        LexicalScope lexicalScope = null;
    3.96 +        PropertyMap lexicalMap = null;
    3.97 +        boolean hasLexicalDefinitions = false;
    3.98 +
    3.99 +        if (context.getEnv()._es6) {
   3.100 +            lexicalScope = (LexicalScope) getLexicalScope();
   3.101 +            lexicalMap = lexicalScope.getMap();
   3.102 +
   3.103 +            for (final jdk.nashorn.internal.runtime.Property property : properties) {
   3.104 +                if (property.isLexicalBinding()) {
   3.105 +                    hasLexicalDefinitions = true;
   3.106 +                }
   3.107 +                // ES6 15.1.8 steps 6. and 7.
   3.108 +                final jdk.nashorn.internal.runtime.Property globalProperty = ownMap.findProperty(property.getKey());
   3.109 +                if (globalProperty != null && !globalProperty.isConfigurable() && property.isLexicalBinding()) {
   3.110 +                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
   3.111 +                }
   3.112 +                final jdk.nashorn.internal.runtime.Property lexicalProperty = lexicalMap.findProperty(property.getKey());
   3.113 +                if (lexicalProperty != null && !property.isConfigurable()) {
   3.114 +                    throw ECMAErrors.syntaxError("redeclare.variable", property.getKey());
   3.115 +                }
   3.116 +            }
   3.117 +        }
   3.118 +
   3.119 +        for (final jdk.nashorn.internal.runtime.Property property : properties) {
   3.120 +            if (property.isLexicalBinding()) {
   3.121 +                assert lexicalScope != null;
   3.122 +                lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
   3.123 +
   3.124 +                if (ownMap.findProperty(property.getKey()) != null) {
   3.125 +                    // If property exists in the global object invalidate any global constant call sites.
   3.126 +                    invalidateGlobalConstant(property.getKey());
   3.127 +                }
   3.128 +            } else {
   3.129 +                ownMap = addBoundProperty(ownMap, source, property);
   3.130 +            }
   3.131 +        }
   3.132 +
   3.133 +        setMap(ownMap);
   3.134 +
   3.135 +        if (hasLexicalDefinitions) {
   3.136 +            lexicalScope.setMap(lexicalMap);
   3.137 +            invalidateLexicalSwitchPoint();
   3.138 +        }
   3.139 +    }
   3.140 +
   3.141 +    @Override
   3.142 +    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
   3.143 +        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
   3.144 +        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
   3.145 +
   3.146 +        if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
   3.147 +            if (lexicalScope.hasOwnProperty(name)) {
   3.148 +                return lexicalScope.findGetMethod(desc, request, operator);
   3.149 +            }
   3.150 +        }
   3.151 +
   3.152 +        final GuardedInvocation invocation =  super.findGetMethod(desc, request, operator);
   3.153 +
   3.154 +        // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
   3.155 +        // because those are invalidated per-key in the addBoundProperties method above.
   3.156 +        // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
   3.157 +        // assuming this only applies to global constants. If other non-inherited properties will
   3.158 +        // start using switchpoints some time in the future we'll have to revisit this.
   3.159 +        if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
   3.160 +            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
   3.161 +        }
   3.162 +
   3.163 +        return invocation;
   3.164 +    }
   3.165 +
   3.166 +    @Override
   3.167 +    public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
   3.168 +        final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
   3.169 +
   3.170 +        if (lexicalScope != null && isScope) {
   3.171 +            final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
   3.172 +            if (lexicalScope.hasOwnProperty(name)) {
   3.173 +                return lexicalScope.findSetMethod(desc, request);
   3.174 +            }
   3.175 +        }
   3.176 +
   3.177 +        final GuardedInvocation invocation = super.findSetMethod(desc, request);
   3.178 +
   3.179 +        if (isScope && context.getEnv()._es6) {
   3.180 +            return invocation.addSwitchPoint(getLexicalScopeSwitchPoint());
   3.181 +        }
   3.182 +
   3.183 +        return invocation;
   3.184 +    }
   3.185 +
   3.186 +    private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
   3.187 +        SwitchPoint switchPoint = lexicalScopeSwitchPoint;
   3.188 +        if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
   3.189 +            switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
   3.190 +        }
   3.191 +        return switchPoint;
   3.192 +    }
   3.193 +
   3.194 +    private synchronized void invalidateLexicalSwitchPoint() {
   3.195 +        if (lexicalScopeSwitchPoint != null) {
   3.196 +            context.getLogger(GlobalConstants.class).info("Invalidating non-constant globals on lexical scope update");
   3.197 +            SwitchPoint.invalidateAll(new SwitchPoint[]{ lexicalScopeSwitchPoint });
   3.198 +        }
   3.199 +    }
   3.200 +
   3.201 +
   3.202 +    @SuppressWarnings("unused")
   3.203 +    private static Object lexicalScopeFilter(final Object self) {
   3.204 +        if (self instanceof Global) {
   3.205 +            return ((Global) self).getLexicalScope();
   3.206 +        }
   3.207 +        return self;
   3.208 +    }
   3.209 +
   3.210      private <T extends ScriptObject> T initConstructorAndSwitchPoint(final String name, final Class<T> clazz) {
   3.211          final T func = initConstructor(name, clazz);
   3.212          tagBuiltinProperties(name, func);
   3.213 @@ -1739,7 +1879,7 @@
   3.214          this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
   3.215          this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
   3.216          this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
   3.217 -        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
   3.218 +        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
   3.219          this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
   3.220          this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
   3.221  
   3.222 @@ -2205,4 +2345,36 @@
   3.223      protected boolean isGlobal() {
   3.224          return true;
   3.225      }
   3.226 +
   3.227 +    /**
   3.228 +     * A class representing the ES6 global lexical scope.
   3.229 +     */
   3.230 +    private static class LexicalScope extends ScriptObject {
   3.231 +
   3.232 +        LexicalScope(final ScriptObject proto) {
   3.233 +            super(proto, PropertyMap.newMap());
   3.234 +        }
   3.235 +
   3.236 +        @Override
   3.237 +        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
   3.238 +            return filterInvocation(super.findGetMethod(desc, request, operator));
   3.239 +        }
   3.240 +
   3.241 +        @Override
   3.242 +        protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
   3.243 +            return filterInvocation(super.findSetMethod(desc, request));
   3.244 +        }
   3.245 +
   3.246 +        @Override
   3.247 +        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
   3.248 +            // We override this method just to make it callable by Global
   3.249 +            return super.addBoundProperty(propMap, source, property);
   3.250 +        }
   3.251 +
   3.252 +        private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
   3.253 +            final MethodType type = invocation.getInvocation().type();
   3.254 +            return invocation.asType(type.changeParameterType(0, Object.class)).filterArguments(0, LEXICAL_SCOPE_FILTER);
   3.255 +        }
   3.256 +    }
   3.257 +
   3.258  }
     4.1 --- a/src/jdk/nashorn/internal/parser/Parser.java	Fri Nov 21 20:17:02 2014 +0100
     4.2 +++ b/src/jdk/nashorn/internal/parser/Parser.java	Mon Nov 24 12:03:15 2014 +0100
     4.3 @@ -707,20 +707,9 @@
     4.4              FunctionNode.Kind.SCRIPT,
     4.5              functionLine);
     4.6  
     4.7 -        // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations.
     4.8 -        final int startLine = start;
     4.9 -        Block outer = useBlockScope() ? newBlock() : null;
    4.10          functionDeclarations = new ArrayList<>();
    4.11 -
    4.12 -        try {
    4.13 -            sourceElements(allowPropertyFunction);
    4.14 -            addFunctionDeclarations(script);
    4.15 -        } finally {
    4.16 -            if (outer != null) {
    4.17 -                outer = restoreBlock(outer);
    4.18 -                appendStatement(new BlockStatement(startLine, outer));
    4.19 -            }
    4.20 -        }
    4.21 +        sourceElements(allowPropertyFunction);
    4.22 +        addFunctionDeclarations(script);
    4.23          functionDeclarations = null;
    4.24  
    4.25          expect(EOF);
     5.1 --- a/src/jdk/nashorn/internal/runtime/Property.java	Fri Nov 21 20:17:02 2014 +0100
     5.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java	Mon Nov 24 12:03:15 2014 +0100
     5.3 @@ -84,14 +84,17 @@
     5.4      public static final int IS_NASGEN_PRIMITIVE     = 1 << 6;
     5.5  
     5.6      /** Is this a builtin property, e.g. Function.prototype.apply */
     5.7 -    public static final int IS_BUILTIN = 1 << 7;
     5.8 +    public static final int IS_BUILTIN              = 1 << 7;
     5.9  
    5.10      /** Is this property bound to a receiver? This means get/set operations will be delegated to
    5.11       *  a statically defined object instead of the object passed as callsite parameter. */
    5.12 -    public static final int IS_BOUND                = 1 << 7;
    5.13 +    public static final int IS_BOUND                = 1 << 8;
    5.14  
    5.15      /** Is this a lexically scoped LET or CONST variable that is dead until it is declared. */
    5.16 -    public static final int NEEDS_DECLARATION       = 1 << 8;
    5.17 +    public static final int NEEDS_DECLARATION       = 1 << 9;
    5.18 +
    5.19 +    /** Is this property an ES6 lexical binding? */
    5.20 +    public static final int IS_LEXICAL_BINDING      = 1 << 10;
    5.21  
    5.22      /** Property key. */
    5.23      private final String key;
    5.24 @@ -714,4 +717,12 @@
    5.25      public boolean isFunctionDeclaration() {
    5.26          return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
    5.27      }
    5.28 +
    5.29 +    /**
    5.30 +     * Is this a property defined by ES6 let or const?
    5.31 +     * @return true if this property represents a lexical binding.
    5.32 +     */
    5.33 +    public boolean isLexicalBinding() {
    5.34 +        return (flags & IS_LEXICAL_BINDING) == IS_LEXICAL_BINDING;
    5.35 +    }
    5.36  }
     6.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Nov 21 20:17:02 2014 +0100
     6.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Nov 24 12:03:15 2014 +0100
     6.3 @@ -304,29 +304,44 @@
     6.4          PropertyMap newMap = this.getMap();
     6.5  
     6.6          for (final Property property : properties) {
     6.7 -            final String key = property.getKey();
     6.8 -            final Property oldProp = newMap.findProperty(key);
     6.9 -            if (oldProp == null) {
    6.10 -                if (property instanceof UserAccessorProperty) {
    6.11 -                    // Note: we copy accessor functions to this object which is semantically different from binding.
    6.12 -                    final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
    6.13 -                    newMap = newMap.addPropertyNoHistory(prop);
    6.14 -                } else {
    6.15 -                    newMap = newMap.addPropertyBind((AccessorProperty)property, source);
    6.16 -                }
    6.17 +            newMap = addBoundProperty(newMap, source, property);
    6.18 +        }
    6.19 +
    6.20 +        this.setMap(newMap);
    6.21 +    }
    6.22 +
    6.23 +    /**
    6.24 +     * Add a bound property from {@code source}, using the interim property map {@code propMap}, and return the
    6.25 +     * new interim property map.
    6.26 +     *
    6.27 +     * @param propMap the property map
    6.28 +     * @param source the source object
    6.29 +     * @param property the property to be added
    6.30 +     * @return the new property map
    6.31 +     */
    6.32 +    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
    6.33 +        PropertyMap newMap = propMap;
    6.34 +        final String key = property.getKey();
    6.35 +        final Property oldProp = newMap.findProperty(key);
    6.36 +        if (oldProp == null) {
    6.37 +            if (property instanceof UserAccessorProperty) {
    6.38 +                // Note: we copy accessor functions to this object which is semantically different from binding.
    6.39 +                final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
    6.40 +                newMap = newMap.addPropertyNoHistory(prop);
    6.41              } else {
    6.42 -                // See ECMA section 10.5 Declaration Binding Instantiation
    6.43 -                // step 5 processing each function declaration.
    6.44 -                if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
    6.45 -                     if (oldProp instanceof UserAccessorProperty ||
    6.46 -                         !(oldProp.isWritable() && oldProp.isEnumerable())) {
    6.47 -                         throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
    6.48 -                     }
    6.49 +                newMap = newMap.addPropertyBind((AccessorProperty)property, source);
    6.50 +            }
    6.51 +        } else {
    6.52 +            // See ECMA section 10.5 Declaration Binding Instantiation
    6.53 +            // step 5 processing each function declaration.
    6.54 +            if (property.isFunctionDeclaration() && !oldProp.isConfigurable()) {
    6.55 +                if (oldProp instanceof UserAccessorProperty ||
    6.56 +                        !(oldProp.isWritable() && oldProp.isEnumerable())) {
    6.57 +                    throw typeError("cant.redefine.property", key, ScriptRuntime.safeToString(this));
    6.58                  }
    6.59              }
    6.60          }
    6.61 -
    6.62 -        this.setMap(newMap);
    6.63 +        return newMap;
    6.64      }
    6.65  
    6.66      /**
    6.67 @@ -510,7 +525,11 @@
    6.68          }
    6.69      }
    6.70  
    6.71 -    private void invalidateGlobalConstant(final String key) {
    6.72 +    /**
    6.73 +     * Invalidate any existing global constant method handles that may exist for {@code key}.
    6.74 +     * @param key the property name
    6.75 +     */
    6.76 +    protected void invalidateGlobalConstant(final String key) {
    6.77          final GlobalConstants globalConstants = getGlobalConstants();
    6.78          if (globalConstants != null) {
    6.79              globalConstants.delete(key);
     7.1 --- a/test/script/basic/es6/const-redeclare-extra.js.EXPECTED	Fri Nov 21 20:17:02 2014 +0100
     7.2 +++ b/test/script/basic/es6/const-redeclare-extra.js.EXPECTED	Mon Nov 24 12:03:15 2014 +0100
     7.3 @@ -1,9 +1,9 @@
     7.4  SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:8 Variable "x" has already been declared
     7.5      var x = {};
     7.6          ^
     7.7 -SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:8 Variable "x" has already been declared
     7.8 -    var x = 2;
     7.9 -        ^
    7.10 -SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:2:13 Variable "x" has already been declared
    7.11 -    function x () {}
    7.12 -             ^
    7.13 +SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
    7.14 +    const x = {};
    7.15 +          ^
    7.16 +SyntaxError: test/script/basic/es6/const-redeclare-extra.js#36:8<eval>:3:10 Variable "x" has already been declared
    7.17 +    const x = 5;
    7.18 +          ^
     8.1 --- a/test/script/basic/es6/let-load.js	Fri Nov 21 20:17:02 2014 +0100
     8.2 +++ b/test/script/basic/es6/let-load.js	Mon Nov 24 12:03:15 2014 +0100
     8.3 @@ -26,7 +26,8 @@
     8.4   *
     8.5   * @test
     8.6   * @run
     8.7 - * @option --language=es6 */
     8.8 + * @option --language=es6
     8.9 + */
    8.10  
    8.11  "use strict";
    8.12  
     9.1 --- a/test/script/basic/es6/let-load.js.EXPECTED	Fri Nov 21 20:17:02 2014 +0100
     9.2 +++ b/test/script/basic/es6/let-load.js.EXPECTED	Mon Nov 24 12:03:15 2014 +0100
     9.3 @@ -2,7 +2,7 @@
     9.4  block function
     9.5  print local defs: 20 30
     9.6  imported var: 1
     9.7 -ReferenceError: "b" is not defined
     9.8 -ReferenceError: "c" is not defined
     9.9 +imported let: 2
    9.10 +imported const: 3
    9.11  top level function
    9.12  ReferenceError: "block" is not defined
    10.1 --- a/test/script/basic/es6/let-redeclare-extra.js.EXPECTED	Fri Nov 21 20:17:02 2014 +0100
    10.2 +++ b/test/script/basic/es6/let-redeclare-extra.js.EXPECTED	Mon Nov 24 12:03:15 2014 +0100
    10.3 @@ -4,12 +4,12 @@
    10.4  SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
    10.5      var x = 2;
    10.6          ^
    10.7 -SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "x" has already been declared
    10.8 -    var x = 2;
    10.9 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:8 Variable "x" has already been declared
   10.10 +    let x = undefined;
   10.11          ^
   10.12  SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:10 Variable "x" has already been declared
   10.13      const x = function (){};
   10.14            ^
   10.15 -SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:3:13 Variable "a" has already been declared
   10.16 -    function a () {};
   10.17 -             ^
   10.18 +SyntaxError: test/script/basic/es6/let-redeclare-extra.js#35:8<eval>:2:8 Variable "a" has already been declared
   10.19 +    let a = 2;
   10.20 +        ^
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/script/basic/es6/lexical-toplevel-def.js	Mon Nov 24 12:03:15 2014 +0100
    11.3 @@ -0,0 +1,34 @@
    11.4 +/*
    11.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + * 
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.
   11.11 + * 
   11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.15 + * version 2 for more details (a copy is included in the LICENSE file that
   11.16 + * accompanied this code).
   11.17 + * 
   11.18 + * You should have received a copy of the GNU General Public License version
   11.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.21 + * 
   11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.23 + * or visit www.oracle.com if you need additional information or have any
   11.24 + * questions.
   11.25 + */
   11.26 +
   11.27 +/**
   11.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   11.29 + *
   11.30 + * @subtest
   11.31 + */
   11.32 +
   11.33 +var   VAR   = "VAR";
   11.34 +let   LET   = "LET";
   11.35 +const CONST = "CONST";
   11.36 +function FUNC() {}
   11.37 +this.GLOBAL = "GLOBAL";
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/script/basic/es6/lexical-toplevel-print.js	Mon Nov 24 12:03:15 2014 +0100
    12.3 @@ -0,0 +1,51 @@
    12.4 +/*
    12.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + * 
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.
   12.11 + * 
   12.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.15 + * version 2 for more details (a copy is included in the LICENSE file that
   12.16 + * accompanied this code).
   12.17 + * 
   12.18 + * You should have received a copy of the GNU General Public License version
   12.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.21 + * 
   12.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.23 + * or visit www.oracle.com if you need additional information or have any
   12.24 + * questions.
   12.25 + */
   12.26 +
   12.27 +/**
   12.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   12.29 + *
   12.30 + * @subtest
   12.31 + */
   12.32 +
   12.33 +print(VAR);
   12.34 +print(LET);
   12.35 +print(CONST);
   12.36 +print(FUNC);
   12.37 +print(GLOBAL);
   12.38 +print(this.VAR);
   12.39 +print(this.LET);   // undefined
   12.40 +print(this.CONST); // undefined
   12.41 +print(this.FUNC);
   12.42 +print(this.GLOBAL);
   12.43 +print("VAR" in this);
   12.44 +print("LET" in this);   // false
   12.45 +print("CONST" in this); // false
   12.46 +print("FUNC" in this);
   12.47 +print("GLOBAL" in this);
   12.48 +
   12.49 +try {
   12.50 +    LET   = LET + "LET";
   12.51 +    CONST = CONST + "CONST";
   12.52 +} catch (e) {
   12.53 +    print(String(e).replace(/\\/g, "/"));
   12.54 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-func-on-let.js	Mon Nov 24 12:03:15 2014 +0100
    13.3 @@ -0,0 +1,31 @@
    13.4 +/*
    13.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + * 
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.
   13.11 + * 
   13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.15 + * version 2 for more details (a copy is included in the LICENSE file that
   13.16 + * accompanied this code).
   13.17 + * 
   13.18 + * You should have received a copy of the GNU General Public License version
   13.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.21 + * 
   13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.23 + * or visit www.oracle.com if you need additional information or have any
   13.24 + * questions.
   13.25 + */
   13.26 +
   13.27 +/**
   13.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   13.29 + *
   13.30 + * @subtest
   13.31 + */
   13.32 +
   13.33 +function LET() {}
   13.34 +var SHOULD_NOT_EXIST = 10;
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-builtin.js	Mon Nov 24 12:03:15 2014 +0100
    14.3 @@ -0,0 +1,30 @@
    14.4 +/*
    14.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + * 
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.
   14.11 + * 
   14.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.15 + * version 2 for more details (a copy is included in the LICENSE file that
   14.16 + * accompanied this code).
   14.17 + * 
   14.18 + * You should have received a copy of the GNU General Public License version
   14.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.21 + * 
   14.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.23 + * or visit www.oracle.com if you need additional information or have any
   14.24 + * questions.
   14.25 + */
   14.26 +
   14.27 +/**
   14.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   14.29 + *
   14.30 + * @subtest
   14.31 + */
   14.32 +
   14.33 +let Object = "LEXICAL BUILTIN";
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-func.js	Mon Nov 24 12:03:15 2014 +0100
    15.3 @@ -0,0 +1,31 @@
    15.4 +/*
    15.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + * 
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.
   15.11 + * 
   15.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.15 + * version 2 for more details (a copy is included in the LICENSE file that
   15.16 + * accompanied this code).
   15.17 + * 
   15.18 + * You should have received a copy of the GNU General Public License version
   15.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.21 + * 
   15.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.23 + * or visit www.oracle.com if you need additional information or have any
   15.24 + * questions.
   15.25 + */
   15.26 +
   15.27 +/**
   15.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   15.29 + *
   15.30 + * @subtest
   15.31 + */
   15.32 +
   15.33 +let FUNC = 10;
   15.34 +var SHOULD_NOT_EXIST = 10;
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-global.js	Mon Nov 24 12:03:15 2014 +0100
    16.3 @@ -0,0 +1,30 @@
    16.4 +/*
    16.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + * 
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.
   16.11 + * 
   16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.15 + * version 2 for more details (a copy is included in the LICENSE file that
   16.16 + * accompanied this code).
   16.17 + * 
   16.18 + * You should have received a copy of the GNU General Public License version
   16.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.21 + * 
   16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.23 + * or visit www.oracle.com if you need additional information or have any
   16.24 + * questions.
   16.25 + */
   16.26 +
   16.27 +/**
   16.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   16.29 + *
   16.30 + * @subtest
   16.31 + */
   16.32 +
   16.33 +let GLOBAL = "LEXICAL GLOBAL";
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-let-on-var.js	Mon Nov 24 12:03:15 2014 +0100
    17.3 @@ -0,0 +1,31 @@
    17.4 +/*
    17.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 + * 
    17.8 + * This code is free software; you can redistribute it and/or modify it
    17.9 + * under the terms of the GNU General Public License version 2 only, as
   17.10 + * published by the Free Software Foundation.
   17.11 + * 
   17.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   17.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.15 + * version 2 for more details (a copy is included in the LICENSE file that
   17.16 + * accompanied this code).
   17.17 + * 
   17.18 + * You should have received a copy of the GNU General Public License version
   17.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   17.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.21 + * 
   17.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   17.23 + * or visit www.oracle.com if you need additional information or have any
   17.24 + * questions.
   17.25 + */
   17.26 +
   17.27 +/**
   17.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   17.29 + *
   17.30 + * @subtest
   17.31 + */
   17.32 +
   17.33 +let VAR = 10;
   17.34 +var SHOULD_NOT_EXIST = 10;
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare-var-on-let.js	Mon Nov 24 12:03:15 2014 +0100
    18.3 @@ -0,0 +1,31 @@
    18.4 +/*
    18.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.7 + * 
    18.8 + * This code is free software; you can redistribute it and/or modify it
    18.9 + * under the terms of the GNU General Public License version 2 only, as
   18.10 + * published by the Free Software Foundation.
   18.11 + * 
   18.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   18.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   18.15 + * version 2 for more details (a copy is included in the LICENSE file that
   18.16 + * accompanied this code).
   18.17 + * 
   18.18 + * You should have received a copy of the GNU General Public License version
   18.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   18.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   18.21 + * 
   18.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   18.23 + * or visit www.oracle.com if you need additional information or have any
   18.24 + * questions.
   18.25 + */
   18.26 +
   18.27 +/**
   18.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   18.29 + *
   18.30 + * @subtest
   18.31 + */
   18.32 +
   18.33 +var LET = 10;
   18.34 +var SHOULD_NOT_EXIST = 10;
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare.js	Mon Nov 24 12:03:15 2014 +0100
    19.3 @@ -0,0 +1,78 @@
    19.4 +/*
    19.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + * 
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.
   19.11 + * 
   19.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.15 + * version 2 for more details (a copy is included in the LICENSE file that
   19.16 + * accompanied this code).
   19.17 + * 
   19.18 + * You should have received a copy of the GNU General Public License version
   19.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.21 + * 
   19.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.23 + * or visit www.oracle.com if you need additional information or have any
   19.24 + * questions.
   19.25 + */
   19.26 +
   19.27 +/**
   19.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   19.29 + *
   19.30 + * @test
   19.31 + * @run
   19.32 + * @option -scripting
   19.33 + * @option --language=es6
   19.34 + */
   19.35 +
   19.36 +load(__DIR__ + "lexical-toplevel-def.js");
   19.37 +
   19.38 +var global = this;
   19.39 +
   19.40 +function tryIt (code) {
   19.41 +    try {
   19.42 +        eval(code)
   19.43 +    } catch (e) {
   19.44 +        print(String(e).replace(/\\/g, "/"))
   19.45 +    }
   19.46 +}
   19.47 +
   19.48 +function loadScript(script) {
   19.49 +    print(script);
   19.50 +    try {
   19.51 +        load(__DIR__ + script);
   19.52 +    } catch (e) {
   19.53 +        print(String(e).replace(/\\/g, "/"));
   19.54 +    }
   19.55 +    print(VAR);
   19.56 +    print(LET);
   19.57 +    print(CONST);
   19.58 +    print(FUNC);
   19.59 +    print(GLOBAL);
   19.60 +    print(global.VAR);
   19.61 +    print(global.LET);
   19.62 +    print(global.CONST);
   19.63 +    print(global.FUNC);
   19.64 +    print(global.GLOBAL);
   19.65 +    try {
   19.66 +        print(SHOULD_NOT_EXIST);
   19.67 +    } catch (e) {
   19.68 +        print(String(e).replace(/\\/g, "/"));
   19.69 +    }
   19.70 +    print(global.SHOULD_NOT_EXIST);
   19.71 +    print(Object);
   19.72 +    print(global.Object);
   19.73 +    print();
   19.74 +}
   19.75 +
   19.76 +loadScript("lexical-toplevel-redeclare-var-on-let.js");
   19.77 +loadScript("lexical-toplevel-redeclare-func-on-let.js");
   19.78 +loadScript("lexical-toplevel-redeclare-let-on-var.js");
   19.79 +loadScript("lexical-toplevel-redeclare-let-on-func.js");
   19.80 +loadScript("lexical-toplevel-redeclare-let-on-builtin.js");
   19.81 +loadScript("lexical-toplevel-redeclare-let-on-global.js");
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/script/basic/es6/lexical-toplevel-redeclare.js.EXPECTED	Mon Nov 24 12:03:15 2014 +0100
    20.3 @@ -0,0 +1,100 @@
    20.4 +lexical-toplevel-redeclare-var-on-let.js
    20.5 +SyntaxError: Variable "LET" has already been declared
    20.6 +VAR
    20.7 +LET
    20.8 +CONST
    20.9 +function FUNC() {}
   20.10 +GLOBAL
   20.11 +VAR
   20.12 +undefined
   20.13 +undefined
   20.14 +function FUNC() {}
   20.15 +GLOBAL
   20.16 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
   20.17 +undefined
   20.18 +function Object() { [native code] }
   20.19 +function Object() { [native code] }
   20.20 +
   20.21 +lexical-toplevel-redeclare-func-on-let.js
   20.22 +SyntaxError: Variable "LET" has already been declared
   20.23 +VAR
   20.24 +LET
   20.25 +CONST
   20.26 +function FUNC() {}
   20.27 +GLOBAL
   20.28 +VAR
   20.29 +undefined
   20.30 +undefined
   20.31 +function FUNC() {}
   20.32 +GLOBAL
   20.33 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
   20.34 +undefined
   20.35 +function Object() { [native code] }
   20.36 +function Object() { [native code] }
   20.37 +
   20.38 +lexical-toplevel-redeclare-let-on-var.js
   20.39 +SyntaxError: Variable "VAR" has already been declared
   20.40 +VAR
   20.41 +LET
   20.42 +CONST
   20.43 +function FUNC() {}
   20.44 +GLOBAL
   20.45 +VAR
   20.46 +undefined
   20.47 +undefined
   20.48 +function FUNC() {}
   20.49 +GLOBAL
   20.50 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
   20.51 +undefined
   20.52 +function Object() { [native code] }
   20.53 +function Object() { [native code] }
   20.54 +
   20.55 +lexical-toplevel-redeclare-let-on-func.js
   20.56 +SyntaxError: Variable "FUNC" has already been declared
   20.57 +VAR
   20.58 +LET
   20.59 +CONST
   20.60 +function FUNC() {}
   20.61 +GLOBAL
   20.62 +VAR
   20.63 +undefined
   20.64 +undefined
   20.65 +function FUNC() {}
   20.66 +GLOBAL
   20.67 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
   20.68 +undefined
   20.69 +function Object() { [native code] }
   20.70 +function Object() { [native code] }
   20.71 +
   20.72 +lexical-toplevel-redeclare-let-on-builtin.js
   20.73 +VAR
   20.74 +LET
   20.75 +CONST
   20.76 +function FUNC() {}
   20.77 +GLOBAL
   20.78 +VAR
   20.79 +undefined
   20.80 +undefined
   20.81 +function FUNC() {}
   20.82 +GLOBAL
   20.83 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
   20.84 +undefined
   20.85 +LEXICAL BUILTIN
   20.86 +function Object() { [native code] }
   20.87 +
   20.88 +lexical-toplevel-redeclare-let-on-global.js
   20.89 +VAR
   20.90 +LET
   20.91 +CONST
   20.92 +function FUNC() {}
   20.93 +LEXICAL GLOBAL
   20.94 +VAR
   20.95 +undefined
   20.96 +undefined
   20.97 +function FUNC() {}
   20.98 +GLOBAL
   20.99 +ReferenceError: "SHOULD_NOT_EXIST" is not defined
  20.100 +undefined
  20.101 +LEXICAL BUILTIN
  20.102 +function Object() { [native code] }
  20.103 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/script/basic/es6/lexical-toplevel.js	Mon Nov 24 12:03:15 2014 +0100
    21.3 @@ -0,0 +1,35 @@
    21.4 +/*
    21.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + * 
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.
   21.11 + * 
   21.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.15 + * version 2 for more details (a copy is included in the LICENSE file that
   21.16 + * accompanied this code).
   21.17 + * 
   21.18 + * You should have received a copy of the GNU General Public License version
   21.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.21 + * 
   21.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.23 + * or visit www.oracle.com if you need additional information or have any
   21.24 + * questions.
   21.25 + */
   21.26 +
   21.27 +/**
   21.28 + * JDK-8057691: Nashorn: let & const declarations are not shared between scripts
   21.29 + *
   21.30 + * @test
   21.31 + * @run
   21.32 + * @option --language=es6
   21.33 + */
   21.34 +
   21.35 +load(__DIR__ + "lexical-toplevel-def.js");
   21.36 +
   21.37 +load(__DIR__ + "lexical-toplevel-print.js");
   21.38 +load(__DIR__ + "lexical-toplevel-print.js");
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/test/script/basic/es6/lexical-toplevel.js.EXPECTED	Mon Nov 24 12:03:15 2014 +0100
    22.3 @@ -0,0 +1,30 @@
    22.4 +VAR
    22.5 +LET
    22.6 +CONST
    22.7 +function FUNC() {}
    22.8 +GLOBAL
    22.9 +VAR
   22.10 +undefined
   22.11 +undefined
   22.12 +function FUNC() {}
   22.13 +GLOBAL
   22.14 +true
   22.15 +false
   22.16 +false
   22.17 +true
   22.18 +true
   22.19 +VAR
   22.20 +LETLET
   22.21 +CONST
   22.22 +function FUNC() {}
   22.23 +GLOBAL
   22.24 +VAR
   22.25 +undefined
   22.26 +undefined
   22.27 +function FUNC() {}
   22.28 +GLOBAL
   22.29 +true
   22.30 +false
   22.31 +false
   22.32 +true
   22.33 +true
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java	Mon Nov 24 12:03:15 2014 +0100
    23.3 @@ -0,0 +1,212 @@
    23.4 +/*
    23.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.7 + *
    23.8 + * This code is free software; you can redistribute it and/or modify it
    23.9 + * under the terms of the GNU General Public License version 2 only, as
   23.10 + * published by the Free Software Foundation.  Oracle designates this
   23.11 + * particular file as subject to the "Classpath" exception as provided
   23.12 + * by Oracle in the LICENSE file that accompanied this code.
   23.13 + *
   23.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   23.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   23.17 + * version 2 for more details (a copy is included in the LICENSE file that
   23.18 + * accompanied this code).
   23.19 + *
   23.20 + * You should have received a copy of the GNU General Public License version
   23.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   23.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   23.23 + *
   23.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   23.25 + * or visit www.oracle.com if you need additional information or have any
   23.26 + * questions.
   23.27 + */
   23.28 +
   23.29 +package jdk.nashorn.internal.runtime;
   23.30 +
   23.31 +import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
   23.32 +import org.testng.annotations.Test;
   23.33 +
   23.34 +import javax.script.Bindings;
   23.35 +import javax.script.ScriptContext;
   23.36 +import javax.script.ScriptEngine;
   23.37 +import javax.script.ScriptException;
   23.38 +import javax.script.SimpleScriptContext;
   23.39 +
   23.40 +import static org.testng.Assert.assertEquals;
   23.41 +
   23.42 +/**
   23.43 + * Top-level lexical binding tests.
   23.44 + *
   23.45 + * @test
   23.46 + * @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
   23.47 + */
   23.48 +@SuppressWarnings("javadoc")
   23.49 +public class LexicalBindingTest {
   23.50 +
   23.51 +    final static String LANGUAGE_ES6 = "--language=es6";
   23.52 +    final static int NUMBER_OF_CONTEXTS = 20;
   23.53 +    final static int MEGAMORPHIC_LOOP_COUNT = 20;
   23.54 +
   23.55 +    /**
   23.56 +     * Test access to global var-declared variables for shared script classes with multiple globals.
   23.57 +     */
   23.58 +    @Test
   23.59 +    public static void megamorphicVarTest() throws ScriptException, InterruptedException {
   23.60 +        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
   23.61 +        final ScriptEngine e = factory.getScriptEngine();
   23.62 +        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
   23.63 +        final String sharedScript = "foo";
   23.64 +
   23.65 +
   23.66 +        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
   23.67 +            final ScriptContext context = contexts[i] = new SimpleScriptContext();
   23.68 +            final Bindings b = e.createBindings();
   23.69 +            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
   23.70 +            assertEquals(e.eval("var foo = '" + i + "';", context), null);
   23.71 +        }
   23.72 +
   23.73 +        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
   23.74 +            final ScriptContext context = contexts[i];
   23.75 +            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
   23.76 +        }
   23.77 +    }
   23.78 +
   23.79 +    /**
   23.80 +     * Test access to global lexically declared variables for shared script classes with multiple globals.
   23.81 +     */
   23.82 +    @Test
   23.83 +    public static void megamorphicMultiGlobalLetTest() throws ScriptException, InterruptedException {
   23.84 +        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
   23.85 +        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
   23.86 +        final ScriptContext[] contexts = new ScriptContext[NUMBER_OF_CONTEXTS];
   23.87 +        final String sharedScript = "foo";
   23.88 +
   23.89 +
   23.90 +        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
   23.91 +            final ScriptContext context = contexts[i] = new SimpleScriptContext();
   23.92 +            final Bindings b = e.createBindings();
   23.93 +            context.setBindings(b, ScriptContext.ENGINE_SCOPE);
   23.94 +            assertEquals(e.eval("let foo = '" + i + "';", context), null);
   23.95 +        }
   23.96 +
   23.97 +        for (int i = 0; i < NUMBER_OF_CONTEXTS; i++) {
   23.98 +            final ScriptContext context = contexts[i];
   23.99 +            assertEquals(e.eval(sharedScript, context), String.valueOf(i));
  23.100 +        }
  23.101 +    }
  23.102 +
  23.103 +
  23.104 +    /**
  23.105 +     * Test access to global lexically declared variables for shared script classes with single global.
  23.106 +     */
  23.107 +    @Test
  23.108 +    public static void megamorphicSingleGlobalLetTest() throws ScriptException, InterruptedException {
  23.109 +        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  23.110 +        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
  23.111 +        final String sharedGetterScript = "foo";
  23.112 +        final String sharedSetterScript = "foo = 1";
  23.113 +
  23.114 +        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
  23.115 +            assertEquals(e.eval(sharedSetterScript), 1);
  23.116 +            assertEquals(e.eval(sharedGetterScript), 1);
  23.117 +            assertEquals(e.eval("delete foo; a" + i + " = 1; foo = " + i + ";"), i);
  23.118 +            assertEquals(e.eval(sharedGetterScript), i);
  23.119 +        }
  23.120 +
  23.121 +        assertEquals(e.eval("let foo = 'foo';"), null);
  23.122 +        assertEquals(e.eval(sharedGetterScript), "foo");
  23.123 +        assertEquals(e.eval(sharedSetterScript), 1);
  23.124 +        assertEquals(e.eval(sharedGetterScript), 1);
  23.125 +        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
  23.126 +    }
  23.127 +
  23.128 +    /**
  23.129 +     * Test access to global lexically declared variables for shared script classes with single global.
  23.130 +     */
  23.131 +    @Test
  23.132 +    public static void megamorphicInheritedGlobalLetTest() throws ScriptException, InterruptedException {
  23.133 +        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  23.134 +        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
  23.135 +        final String sharedGetterScript = "foo";
  23.136 +        final String sharedSetterScript = "foo = 1";
  23.137 +
  23.138 +        for (int i = 0; i < MEGAMORPHIC_LOOP_COUNT; i++) {
  23.139 +            assertEquals(e.eval(sharedSetterScript), 1);
  23.140 +            assertEquals(e.eval(sharedGetterScript), 1);
  23.141 +            assertEquals(e.eval("delete foo; a" + i + " = 1; Object.prototype.foo = " + i + ";"), i);
  23.142 +            assertEquals(e.eval(sharedGetterScript), i);
  23.143 +        }
  23.144 +
  23.145 +        assertEquals(e.eval("let foo = 'foo';"), null);
  23.146 +        assertEquals(e.eval(sharedGetterScript), "foo");
  23.147 +        assertEquals(e.eval(sharedSetterScript), 1);
  23.148 +        assertEquals(e.eval(sharedGetterScript), 1);
  23.149 +        assertEquals(e.eval("this.foo"), MEGAMORPHIC_LOOP_COUNT - 1);
  23.150 +    }
  23.151 +
  23.152 +    /**
  23.153 +     * Test multi-threaded access to global lexically declared variables for shared script classes with multiple globals.
  23.154 +     */
  23.155 +    @Test
  23.156 +    public static void multiThreadedLetTest() throws ScriptException, InterruptedException {
  23.157 +        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
  23.158 +        final ScriptEngine e = factory.getScriptEngine(LANGUAGE_ES6);
  23.159 +        final Bindings b = e.createBindings();
  23.160 +        final ScriptContext origContext = e.getContext();
  23.161 +        final ScriptContext newCtxt = new SimpleScriptContext();
  23.162 +        newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
  23.163 +        final String sharedScript = "foo";
  23.164 +
  23.165 +        assertEquals(e.eval("let foo = 'original context';", origContext), null);
  23.166 +        assertEquals(e.eval("let foo = 'new context';", newCtxt), null);
  23.167 +
  23.168 +        final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
  23.169 +        final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
  23.170 +        t1.start();
  23.171 +        t2.start();
  23.172 +        t1.join();
  23.173 +        t2.join();
  23.174 +
  23.175 +        assertEquals(e.eval("foo = 'newer context';", newCtxt), "newer context");
  23.176 +        final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
  23.177 +        final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
  23.178 +
  23.179 +        t3.start();
  23.180 +        t4.start();
  23.181 +        t3.join();
  23.182 +        t4.join();
  23.183 +
  23.184 +        assertEquals(e.eval(sharedScript), "original context");
  23.185 +        assertEquals(e.eval(sharedScript, newCtxt), "newer context");
  23.186 +    }
  23.187 +
  23.188 +    private static class ScriptRunner implements Runnable {
  23.189 +
  23.190 +        final ScriptEngine engine;
  23.191 +        final ScriptContext context;
  23.192 +        final String source;
  23.193 +        final Object expected;
  23.194 +        final int iterations;
  23.195 +
  23.196 +        ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
  23.197 +            this.engine = engine;
  23.198 +            this.context = context;
  23.199 +            this.source = source;
  23.200 +            this.expected = expected;
  23.201 +            this.iterations = iterations;
  23.202 +        }
  23.203 +
  23.204 +        @Override
  23.205 +        public void run() {
  23.206 +            try {
  23.207 +                for (int i = 0; i < iterations; i++) {
  23.208 +                    assertEquals(engine.eval(source, context), expected);
  23.209 +                }
  23.210 +            } catch (final ScriptException se) {
  23.211 +                throw new RuntimeException(se);
  23.212 +            }
  23.213 +        }
  23.214 +    }
  23.215 +}

mercurial