8006984: Introducing local into a function inside with statement confuses its scope

Mon, 25 Feb 2013 16:51:04 +0100

author
attila
date
Mon, 25 Feb 2013 16:51:04 +0100
changeset 120
1654918e0612
parent 119
5610ac25d8ff
child 121
a90094ae5be3

8006984: Introducing local into a function inside with statement confuses its scope
Reviewed-by: jlaskey, lagergren, sundar

src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/WithObject.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8006984.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8006984.js.EXPECTED file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Feb 25 18:13:23 2013 +0530
     1.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Feb 25 16:51:04 2013 +0100
     1.3 @@ -628,14 +628,15 @@
     1.4       * @return FindPropertyData or null if not found.
     1.5       */
     1.6      public final FindProperty findProperty(final String key, final boolean deep) {
     1.7 -        return findProperty(key, deep, false);
     1.8 +        return findProperty(key, deep, false, this);
     1.9      }
    1.10  
    1.11      /**
    1.12       * Low level property API (not using property descriptors)
    1.13       * <p>
    1.14 -     * Find a property in the prototype hierarchy. Note: this is final and not
    1.15 -     * a good idea to override. If you have to, use
    1.16 +     * Find a property in the prototype hierarchy. Note: this is not a good idea
    1.17 +     * to override except as it was done in {@link WithObject}.
    1.18 +     * If you have to, use
    1.19       * {jdk.nashorn.internal.objects.NativeArray{@link #getProperty(String)} or
    1.20       * {jdk.nashorn.internal.objects.NativeArray{@link #getPropertyDescriptor(String)} as the
    1.21       * overriding way to find array properties
    1.22 @@ -645,27 +646,29 @@
    1.23       * @param key  Property key.
    1.24       * @param deep Whether the search should look up proto chain.
    1.25       * @param stopOnNonScope should a deep search stop on the first non-scope object?
    1.26 +     * @param start the object on which the lookup was originally initiated
    1.27       *
    1.28       * @return FindPropertyData or null if not found.
    1.29       */
    1.30 -    public final FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope) {
    1.31 -        for (ScriptObject self = this; self != null; self = self.getProto()) {
    1.32 -            // if doing deep search, stop search on the first non-scope object if asked to do so
    1.33 -            if (stopOnNonScope && self != this && !self.isScope()) {
    1.34 -                return null;
    1.35 +    FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
    1.36 +        // if doing deep search, stop search on the first non-scope object if asked to do so
    1.37 +        if (stopOnNonScope && start != this && !isScope()) {
    1.38 +            return null;
    1.39 +        }
    1.40 +
    1.41 +        final PropertyMap selfMap  = getMap();
    1.42 +        final Property    property = selfMap.findProperty(key);
    1.43 +
    1.44 +        if (property != null) {
    1.45 +            return new FindProperty(start, this, property);
    1.46 +        }
    1.47 +
    1.48 +        if (deep) {
    1.49 +            final ScriptObject proto = getProto();
    1.50 +            if(proto != null) {
    1.51 +                return proto.findProperty(key, deep, stopOnNonScope, start);
    1.52              }
    1.53 -
    1.54 -            final PropertyMap selfMap  = self.getMap();
    1.55 -            final Property    property = selfMap.findProperty(key);
    1.56 -
    1.57 -            if (property != null) {
    1.58 -                return new FindProperty(this, self, property);
    1.59 -            }
    1.60 -
    1.61 -            if (!deep) {
    1.62 -                return null;
    1.63 -            }
    1.64 -         }
    1.65 +        }
    1.66  
    1.67          return null;
    1.68      }
    1.69 @@ -1781,12 +1784,12 @@
    1.70          final boolean scope = isScope();
    1.71          /*
    1.72           * If doing property set on a scope object, we should stop proto search on the first
    1.73 -         * non-scope object. Without this, for exmaple, when assigning "toString" on global scope,
    1.74 +         * non-scope object. Without this, for example, when assigning "toString" on global scope,
    1.75           * we'll end up assigning it on it's proto - which is Object.prototype.toString !!
    1.76           *
    1.77           * toString = function() { print("global toString"); } // don't affect Object.prototype.toString
    1.78           */
    1.79 -        FindProperty find = findProperty(name, true, scope);
    1.80 +        FindProperty find = findProperty(name, true, scope, this);
    1.81          // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
    1.82          if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
    1.83              // We should still check if inherited data property is not writable
     2.1 --- a/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Feb 25 18:13:23 2013 +0530
     2.2 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java	Mon Feb 25 16:51:04 2013 +0100
     2.3 @@ -184,6 +184,28 @@
     2.4          return null;
     2.5      }
     2.6  
     2.7 +    /**
     2.8 +     * Overridden to try to find the property first in the expression object (and its prototypes), and only then in this
     2.9 +     * object (and its prototypes).
    2.10 +     *
    2.11 +     * @param key  Property key.
    2.12 +     * @param deep Whether the search should look up proto chain.
    2.13 +     * @param stopOnNonScope should a deep search stop on the first non-scope object?
    2.14 +     * @param start the object on which the lookup was originally initiated
    2.15 +     *
    2.16 +     * @return FindPropertyData or null if not found.
    2.17 +     */
    2.18 +    @Override
    2.19 +    FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
    2.20 +        if (expression instanceof ScriptObject) {
    2.21 +            final FindProperty exprProperty = ((ScriptObject)expression).findProperty(key, deep, stopOnNonScope, start);
    2.22 +            if(exprProperty != null) {
    2.23 +                return exprProperty;
    2.24 +            }
    2.25 +        }
    2.26 +        return super.findProperty(key, deep, stopOnNonScope, start);
    2.27 +    }
    2.28 +
    2.29      @Override
    2.30      public void setSplitState(final int state) {
    2.31          getNonWithParent().setSplitState(state);
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/script/basic/JDK-8006984.js	Mon Feb 25 16:51:04 2013 +0100
     3.3 @@ -0,0 +1,44 @@
     3.4 +/*
     3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + * 
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + * 
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + * 
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + * 
    3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.23 + * or visit www.oracle.com if you need additional information or have any
    3.24 + * questions.
    3.25 + */
    3.26 +
    3.27 +/**
    3.28 + * findProperty on WithObject was not considering its object argument
    3.29 + * 
    3.30 + * @test
    3.31 + * @run
    3.32 + */
    3.33 +
    3.34 +var guiPkgs = { JFrame: function() { print("created"); } }; 
    3.35 +
    3.36 +with (guiPkgs) { 
    3.37 +     var main = function() { 
    3.38 +        var frame; // <---- this local variable caused scope to be not set properly prior to fix
    3.39 +
    3.40 +        function createFrame() { 
    3.41 +            frame = new JFrame(); 
    3.42 +        } 
    3.43 +
    3.44 +        createFrame(); 
    3.45 +    } 
    3.46 +} 
    3.47 +main();
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/script/basic/JDK-8006984.js.EXPECTED	Mon Feb 25 16:51:04 2013 +0100
     4.3 @@ -0,0 +1,1 @@
     4.4 +created

mercurial