8114838: Anonymous functions escape to surrounding scope when defined under "with" statement
Reviewed-by: attila, hannesw, lagergren
This commit is contained in:
parent
74b5de9db2
commit
d9a4c01c25
44
nashorn/samples/javabind.js
Normal file
44
nashorn/samples/javabind.js
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// bind on a Java method
|
||||
|
||||
// #javascript "bind" function
|
||||
var bind = Function.prototype.bind;
|
||||
|
||||
// Java console object
|
||||
var console = java.lang.System.console();
|
||||
|
||||
// arguments "this" and prompt string of Console.readLine method are bound
|
||||
var readName = bind.call(console.readLine, console, "Your name: ");
|
||||
|
||||
// Now call it like a function that takes no arguments!
|
||||
print("Hello,", readName());
|
69
nashorn/samples/javaconstructorbind.js
Normal file
69
nashorn/samples/javaconstructorbind.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// bind on a Java constructor
|
||||
|
||||
// See Function.prototype.bind:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
||||
var bind = Function.prototype.bind;
|
||||
|
||||
var URL = Java.type("java.net.URL");
|
||||
|
||||
// get the constructor that accepts URL, String parameters.
|
||||
// constructor signatures are properties of type object.
|
||||
var newURL = URL["(URL, String)"];
|
||||
|
||||
// bind "context" URL parameter.
|
||||
var TwitterURL = bind.call(newURL, null, new URL('https://www.twitter.com'));
|
||||
|
||||
// now you can create context relative URLs using the bound constructor
|
||||
print(new TwitterURL("sundararajan_a"));
|
||||
|
||||
// read the URL content and print (optional part)
|
||||
|
||||
var BufferedReader = Java.type("java.io.BufferedReader");
|
||||
var InputStreamReader = Java.type("java.io.InputStreamReader");
|
||||
|
||||
// function to retrieve text content of the given URL
|
||||
function readTextFromURL(url) {
|
||||
var str = '';
|
||||
var u = new URL(url);
|
||||
var reader = new BufferedReader(
|
||||
new InputStreamReader(u.openStream()));
|
||||
try {
|
||||
reader.lines().forEach(function(x) str += x);
|
||||
return str;
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
print(readTextFromURL(new TwitterURL("sundararajan_a")));
|
47
nashorn/samples/mapwith.js
Normal file
47
nashorn/samples/mapwith.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Oracle nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Using a Java map with Javascript "with" statement
|
||||
|
||||
var map = new java.util.HashMap();
|
||||
map.put("foo", 34);
|
||||
map.put("bar", "hello");
|
||||
|
||||
var obj = {
|
||||
__noSuchProperty__: function(name) {
|
||||
return map.get(name);
|
||||
}
|
||||
};
|
||||
|
||||
with(obj) {
|
||||
print(foo);
|
||||
print(bar);
|
||||
}
|
@ -40,7 +40,7 @@ final class FunctionExpressionTreeImpl extends ExpressionTreeImpl
|
||||
final BlockTree body) {
|
||||
super(node);
|
||||
funcNode = node;
|
||||
assert !funcNode.isDeclared() : "function expression expected";
|
||||
assert !funcNode.isDeclared() || funcNode.isAnonymous() : "function expression expected";
|
||||
|
||||
final FunctionNode.Kind kind = node.getKind();
|
||||
if (node.isAnonymous() || kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
|
||||
|
@ -224,7 +224,7 @@ final class IRTranslator extends NodeVisitor<LexicalContext> {
|
||||
|
||||
@Override
|
||||
public boolean enterFunctionNode(final FunctionNode functionNode) {
|
||||
assert !functionNode.isDeclared() : "should not reach here for function declaration";
|
||||
assert !functionNode.isDeclared() || functionNode.isAnonymous() : "should not reach here for function declaration";
|
||||
|
||||
final List<? extends ExpressionTree> paramTrees
|
||||
= translateExprs(functionNode.getParameters());
|
||||
|
@ -551,9 +551,7 @@ final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggabl
|
||||
private void defineVarIdent(final VarNode varNode) {
|
||||
final IdentNode ident = varNode.getName();
|
||||
final int flags;
|
||||
if (varNode.isAnonymousFunctionDeclaration()) {
|
||||
flags = IS_INTERNAL;
|
||||
} else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
|
||||
if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
|
||||
flags = IS_SCOPE;
|
||||
} else {
|
||||
flags = 0;
|
||||
|
@ -312,10 +312,6 @@ final class SplitIntoFunctions extends NodeVisitor<BlockLexicalContext> {
|
||||
assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
|
||||
|
||||
final Expression init = varNode.getInit();
|
||||
if (varNode.isAnonymousFunctionDeclaration()) {
|
||||
// We ain't moving anonymous function declarations.
|
||||
return super.enterVarNode(varNode);
|
||||
}
|
||||
|
||||
// Move a declaration-only var statement to the top of the outermost function.
|
||||
getCurrentFunctionState().varStatements.add(varNode.setInit(null));
|
||||
|
@ -290,12 +290,4 @@ public final class VarNode extends Statement implements Assignment<IdentNode> {
|
||||
public boolean isFunctionDeclaration() {
|
||||
return init instanceof FunctionNode && ((FunctionNode)init).isDeclared();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is an anonymous function declaration.
|
||||
* @return true if this is an anonymous function declaration.
|
||||
*/
|
||||
public boolean isAnonymousFunctionDeclaration() {
|
||||
return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous();
|
||||
}
|
||||
}
|
||||
|
@ -2765,6 +2765,11 @@ loop:
|
||||
functionBody);
|
||||
|
||||
if (isStatement) {
|
||||
if (isAnonymous) {
|
||||
appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
|
||||
return function;
|
||||
}
|
||||
|
||||
// mark ES6 block functions as lexically scoped
|
||||
final int varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
|
||||
final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
|
||||
|
@ -40,4 +40,4 @@ function(x) {
|
||||
|
||||
EOF, print);
|
||||
|
||||
Assert.assertNull(ast.sourceElements[0].name);
|
||||
Assert.assertNull(ast.sourceElements[0].expression.name);
|
||||
|
47
nashorn/test/script/basic/JDK-8114838.js
Normal file
47
nashorn/test/script/basic/JDK-8114838.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* JDK-8114838: Anonymous functions escape to surrounding scope when defined under "with" statement
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
// do *not* introduce new lines! The next line should be 32
|
||||
with({}) { function () {} }
|
||||
if (typeof this["L:32"] != 'undefined') {
|
||||
throw new Error("anonymous name spills into global scope");
|
||||
}
|
||||
|
||||
var func = eval("function() {}");
|
||||
if (typeof func != 'function') {
|
||||
throw new Error("eval of anonymous function does not work!");
|
||||
}
|
||||
|
||||
var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
|
||||
var engine = new ScriptEngineManager().getEngineByName("nashorn");
|
||||
var func2 = engine.eval("function() {}");
|
||||
if (typeof func2 != 'function') {
|
||||
throw new Error("eval of anonymous function does not work from script engine!");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user