8044520: Nashorn cannot execute node.js's express module

Tue, 03 Jun 2014 17:04:23 +0530

author
sundar
date
Tue, 03 Jun 2014 17:04:23 +0530
changeset 866
77f0308eb2e6
parent 865
0005562330fa
child 867
85ad3ce0796f

8044520: Nashorn cannot execute node.js's express module
Reviewed-by: hannesw, lagergren

src/jdk/nashorn/api/scripting/ScriptObjectMirror.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/CodeGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/Global.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/GlobalFunctions.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8044520.js file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Tue Jun 03 13:57:52 2014 +0530
     1.2 +++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java	Tue Jun 03 17:04:23 2014 +0530
     1.3 @@ -496,7 +496,7 @@
     1.4      public void setProto(final Object proto) {
     1.5          inGlobal(new Callable<Void>() {
     1.6              @Override public Void call() {
     1.7 -                sobj.setProtoCheck(unwrap(proto, global));
     1.8 +                sobj.setPrototypeOf(unwrap(proto, global));
     1.9                  return null;
    1.10              }
    1.11          });
     2.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Jun 03 13:57:52 2014 +0530
     2.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Tue Jun 03 17:04:23 2014 +0530
     2.3 @@ -1500,7 +1500,9 @@
     2.4          method.dup();
     2.5          if (protoNode != null) {
     2.6              load(protoNode);
     2.7 -            method.invoke(ScriptObject.SET_PROTO_CHECK);
     2.8 +            // take care of { __proto__: 34 } or some such!
     2.9 +            method.convert(Type.OBJECT);
    2.10 +            method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
    2.11          } else {
    2.12              globalObjectPrototype();
    2.13              method.invoke(ScriptObject.SET_PROTO);
     3.1 --- a/src/jdk/nashorn/internal/objects/Global.java	Tue Jun 03 13:57:52 2014 +0530
     3.2 +++ b/src/jdk/nashorn/internal/objects/Global.java	Tue Jun 03 17:04:23 2014 +0530
     3.3 @@ -1908,8 +1908,8 @@
     3.4  
     3.5          // ES6 draft compliant __proto__ property of Object.prototype
     3.6          // accessors on Object.prototype for "__proto__"
     3.7 -        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", ScriptObject.GETPROTO);
     3.8 -        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", ScriptObject.SETPROTOCHECK);
     3.9 +        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
    3.10 +        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
    3.11          ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
    3.12  
    3.13  
     4.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java	Tue Jun 03 13:57:52 2014 +0530
     4.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java	Tue Jun 03 17:04:23 2014 +0530
     4.3 @@ -25,6 +25,7 @@
     4.4  
     4.5  package jdk.nashorn.internal.objects;
     4.6  
     4.7 +import static jdk.nashorn.internal.lookup.Lookup.MH;
     4.8  import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
     4.9  import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
    4.10  
    4.11 @@ -74,6 +75,9 @@
    4.12   */
    4.13  @ScriptClass("Object")
    4.14  public final class NativeObject {
    4.15 +    public static final MethodHandle GET__PROTO__ = findOwnMH("get__proto__", ScriptObject.class, Object.class);
    4.16 +    public static final MethodHandle SET__PROTO__ = findOwnMH("set__proto__", Object.class, Object.class, Object.class);
    4.17 +
    4.18      private static final Object TO_STRING = new Object();
    4.19  
    4.20      private static InvokeByName getTO_STRING() {
    4.21 @@ -86,6 +90,35 @@
    4.22                  });
    4.23      }
    4.24  
    4.25 +    @SuppressWarnings("unused")
    4.26 +    private static ScriptObject get__proto__(final Object self) {
    4.27 +        // See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__
    4.28 +        // Step 1 Let O be the result of calling ToObject passing the this.
    4.29 +        final Object obj = Global.toObject(self);
    4.30 +        Global.checkObject(obj);
    4.31 +        final ScriptObject sobj = (ScriptObject)obj;
    4.32 +        return sobj.getProto();
    4.33 +    }
    4.34 +
    4.35 +    @SuppressWarnings("unused")
    4.36 +    private static Object set__proto__(final Object self, final Object proto) {
    4.37 +        // See ES6 draft spec: B.2.2.1.2 set Object.prototype.__proto__
    4.38 +        // Step 1
    4.39 +        Global.checkObjectCoercible(self);
    4.40 +        // Step 4
    4.41 +        if (! (self instanceof ScriptObject)) {
    4.42 +            return UNDEFINED;
    4.43 +        }
    4.44 +
    4.45 +        final ScriptObject sobj = (ScriptObject)self;
    4.46 +        // __proto__ assignment ignores non-nulls and non-objects
    4.47 +        // step 3: If Type(proto) is neither Object nor Null, then return undefined.
    4.48 +        if (proto == null || proto instanceof ScriptObject) {
    4.49 +            sobj.setPrototypeOf(proto);
    4.50 +        }
    4.51 +        return UNDEFINED;
    4.52 +    }
    4.53 +
    4.54      private static final MethodType MIRROR_GETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class);
    4.55      private static final MethodType MIRROR_SETTER_TYPE = MethodType.methodType(Object.class, ScriptObjectMirror.class, Object.class);
    4.56  
    4.57 @@ -160,7 +193,7 @@
    4.58      @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    4.59      public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
    4.60          if (obj instanceof ScriptObject) {
    4.61 -            ((ScriptObject)obj).setProtoCheck(proto);
    4.62 +            ((ScriptObject)obj).setPrototypeOf(proto);
    4.63              return obj;
    4.64          } else if (obj instanceof ScriptObjectMirror) {
    4.65              ((ScriptObjectMirror)obj).setProto(proto);
    4.66 @@ -777,4 +810,8 @@
    4.67          return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation,
    4.68                  methodType), false, source);
    4.69      }
    4.70 +
    4.71 +    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
    4.72 +       return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
    4.73 +    }
    4.74  }
     5.1 --- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Tue Jun 03 13:57:52 2014 +0530
     5.2 +++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java	Tue Jun 03 17:04:23 2014 +0530
     5.3 @@ -459,5 +459,4 @@
     5.4      private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
     5.5          return MH.findStatic(MethodHandles.lookup(), GlobalFunctions.class, name, MH.type(rtype, types));
     5.6      }
     5.7 -
     5.8  }
     6.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Jun 03 13:57:52 2014 +0530
     6.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Jun 03 17:04:23 2014 +0530
     6.3 @@ -132,8 +132,6 @@
     6.4  
     6.5      /** Method handle to retrive prototype of this object */
     6.6      public static final MethodHandle GETPROTO           = findOwnMH("getProto", ScriptObject.class);
     6.7 -    /** Method handle to set prototype of this object */
     6.8 -    public static final MethodHandle SETPROTOCHECK      = findOwnMH("setProtoCheck", void.class, Object.class);
     6.9      static final MethodHandle MEGAMORPHIC_GET    = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
    6.10      static final MethodHandle GLOBALFILTER       = findOwnMH("globalFilter", Object.class, Object.class);
    6.11  
    6.12 @@ -160,7 +158,7 @@
    6.13      public static final Call SET_PROTO          = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
    6.14  
    6.15      /** Method handle for setting the proto of a ScriptObject after checking argument */
    6.16 -    public static final Call SET_PROTO_CHECK    = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
    6.17 +    public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
    6.18  
    6.19      /** Method handle for setting the user accessors of a ScriptObject */
    6.20      public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
    6.21 @@ -1127,14 +1125,21 @@
    6.22  
    6.23      /**
    6.24       * Set the __proto__ of an object with checks.
    6.25 +     * This is the built-in operation [[SetPrototypeOf]]
    6.26 +     * See ES6 draft spec: 9.1.2 [[SetPrototypeOf]] (V)
    6.27 +     *
    6.28       * @param newProto Prototype to set.
    6.29       */
    6.30 -    public final void setProtoCheck(final Object newProto) {
    6.31 -        if (!isExtensible()) {
    6.32 -            throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this));
    6.33 -        }
    6.34 -
    6.35 +    public final void setPrototypeOf(final Object newProto) {
    6.36          if (newProto == null || newProto instanceof ScriptObject) {
    6.37 +            if (!isExtensible()) {
    6.38 +                // okay to set same proto again - even if non-extensible
    6.39 +                if (newProto == getProto()) {
    6.40 +                    return;
    6.41 +                }
    6.42 +                throw typeError("__proto__.set.non.extensible", ScriptRuntime.safeToString(this));
    6.43 +            }
    6.44 +
    6.45              // check for circularity
    6.46              ScriptObject p = (ScriptObject)newProto;
    6.47              while (p != null) {
    6.48 @@ -1145,14 +1150,27 @@
    6.49              }
    6.50              setProto((ScriptObject)newProto);
    6.51          } else {
    6.52 -            final Global global = Context.getGlobal();
    6.53 -            final Object  newProtoObject = JSType.toScriptObject(global, newProto);
    6.54 -
    6.55 -            if (newProtoObject instanceof ScriptObject) {
    6.56 -                setProto((ScriptObject)newProtoObject);
    6.57 -            } else {
    6.58 -                throw typeError(global, "cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto));
    6.59 -            }
    6.60 +            throw typeError("cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto));
    6.61 +        }
    6.62 +    }
    6.63 +
    6.64 +    /**
    6.65 +     * Set the __proto__ of an object from an object literal.
    6.66 +     * See ES6 draft spec: B.3.1 __proto__ Property Names in
    6.67 +     * Object Initializers. Step 6 handling of "__proto__".
    6.68 +     *
    6.69 +     * @param newProto Prototype to set.
    6.70 +     */
    6.71 +    public final void setProtoFromLiteral(final Object newProto) {
    6.72 +        if (newProto == null || newProto instanceof ScriptObject) {
    6.73 +            setPrototypeOf(newProto);
    6.74 +        } else {
    6.75 +            // Some non-object, non-null. Then, we need to set
    6.76 +            // Object.prototype as the new __proto__
    6.77 +            //
    6.78 +            // var obj = { __proto__ : 34 };
    6.79 +            // print(obj.__proto__ === Object.prototype); // => true
    6.80 +            setPrototypeOf(Global.objectPrototype());
    6.81          }
    6.82      }
    6.83  
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/script/basic/JDK-8044520.js	Tue Jun 03 17:04:23 2014 +0530
     7.3 @@ -0,0 +1,145 @@
     7.4 +/*
     7.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + * 
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.
    7.11 + * 
    7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.15 + * version 2 for more details (a copy is included in the LICENSE file that
    7.16 + * accompanied this code).
    7.17 + * 
    7.18 + * You should have received a copy of the GNU General Public License version
    7.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.21 + * 
    7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.23 + * or visit www.oracle.com if you need additional information or have any
    7.24 + * questions.
    7.25 + */
    7.26 +
    7.27 +/**
    7.28 + * JDK-8044520: Nashorn cannot execute node.js's express module
    7.29 + *
    7.30 + * @test
    7.31 + * @run
    7.32 + */
    7.33 +
    7.34 +function checkNullProto() {
    7.35 +    var obj = {};
    7.36 +    obj.__proto__ = null;
    7.37 +    var proto = Object.getPrototypeOf(obj);
    7.38 +    if (typeof proto != 'object' || proto !== null) {
    7.39 +        fail("__proto__ can't be set to null!");
    7.40 +    }
    7.41 +}
    7.42 +
    7.43 +checkNullProto();
    7.44 +
    7.45 +function checkSetProto(proto) {
    7.46 +    var obj = {};
    7.47 +    obj.__proto__ = proto;
    7.48 +    if (Object.getPrototypeOf(obj) !== Object.prototype) {
    7.49 +        fail("obj.__proto__ set not ignored for " + proto);
    7.50 +    }
    7.51 +}
    7.52 +
    7.53 +checkSetProto(undefined);
    7.54 +checkSetProto(42);
    7.55 +checkSetProto(false);
    7.56 +checkSetProto("hello");
    7.57 +
    7.58 +function checkLiteralSetProto(proto) {
    7.59 +    var obj = { __proto__: proto };
    7.60 +    if (obj.__proto__ !== Object.prototype) {
    7.61 +        fail("object literal _proto__ set not ignored for " + proto);
    7.62 +    }
    7.63 +}
    7.64 +
    7.65 +checkLiteralSetProto(undefined);
    7.66 +checkLiteralSetProto(34);
    7.67 +checkLiteralSetProto(true);
    7.68 +checkLiteralSetProto("world");
    7.69 +
    7.70 +function checkNullProtoFromLiteral() {
    7.71 +    var obj = { __proto__: null };
    7.72 +    var proto = Object.getPrototypeOf(obj);
    7.73 +    if (typeof proto != 'object' || proto !== null) {
    7.74 +        fail("__proto__ can't be set to null!");
    7.75 +    }
    7.76 +}
    7.77 +
    7.78 +checkNullProtoFromLiteral();
    7.79 +
    7.80 +function checkSetPrototypeOf(proto) {
    7.81 +    try {
    7.82 +        Object.setPrototypeOf({}, proto);
    7.83 +        fail("should have thrown error for " + proto);
    7.84 +    } catch (e) {
    7.85 +        if (! (e instanceof TypeError)) {
    7.86 +            fail("should have thrown TypeError, got " + e);
    7.87 +        }
    7.88 +    }
    7.89 +}
    7.90 +
    7.91 +checkSetPrototypeOf(undefined);
    7.92 +checkSetPrototypeOf(43);
    7.93 +checkSetPrototypeOf(false);
    7.94 +checkSetPrototypeOf("nashorn");
    7.95 +
    7.96 +function checkNullSetPrototypeOf() {
    7.97 +    var obj = { };
    7.98 +    Object.setPrototypeOf(obj, null);
    7.99 +    var proto = Object.getPrototypeOf(obj);
   7.100 +    if (typeof proto != 'object' || proto !== null) {
   7.101 +        fail("__proto__ can't be set to null!");
   7.102 +    }
   7.103 +}
   7.104 +
   7.105 +checkNullSetPrototypeOf();
   7.106 +
   7.107 +var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
   7.108 +
   7.109 +function checkProtoGetterOnPrimitive(value) {
   7.110 +    // call __proto__ getter on primitive - check ToObject
   7.111 +    // is called on 'this' value as per draft spec
   7.112 +    if (desc.get.call(value) !== Object(value).__proto__) {
   7.113 +        fail("can't call __proto__ getter on " + value);
   7.114 +    }
   7.115 +}
   7.116 +
   7.117 +checkProtoGetterOnPrimitive(32);
   7.118 +checkProtoGetterOnPrimitive(false);
   7.119 +checkProtoGetterOnPrimitive("great!");
   7.120 +
   7.121 +function checkProtoSetterOnNonObjectThis(self) {
   7.122 +    try {
   7.123 +        desc.set.call(self);
   7.124 +        fail("should have thrown TypeError");
   7.125 +    } catch (e) {
   7.126 +        if (! (e instanceof TypeError)) {
   7.127 +            fail("should throw TypeError on non-object self, got " +e);
   7.128 +        }
   7.129 +    }
   7.130 +}
   7.131 +
   7.132 +checkProtoSetterOnNonObjectThis(undefined);
   7.133 +checkProtoSetterOnNonObjectThis(null);
   7.134 +
   7.135 +function checkProtoSetterReturnValue(obj, p) {
   7.136 +    if (typeof desc.set.call(obj, p) != "undefined") {
   7.137 +        fail("__proto__ setter does not return undefined: " + obj + " " + p);
   7.138 +    }
   7.139 +}
   7.140 +
   7.141 +// try non-object 'this'. setter is expected to return undefined.
   7.142 +checkProtoSetterReturnValue(23);
   7.143 +checkProtoSetterReturnValue(false);
   7.144 +checkProtoSetterReturnValue("foo");
   7.145 +
   7.146 +// set proper __proto__. Still return value is undefined.
   7.147 +checkProtoSetterReturnValue({}, {});
   7.148 +checkProtoSetterReturnValue({}, null);

mercurial