aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Nevill edward.nevill@linaro.org <Edward Nevill edward.nevill@linaro.org>2014-06-05 13:09:06 +0100
committerEdward Nevill edward.nevill@linaro.org <Edward Nevill edward.nevill@linaro.org>2014-06-05 13:09:06 +0100
commit59d2cf8b7db9dc6cbb1577bc91cf5e82b3a59c0f (patch)
tree70ce8c2934116609e8729bbc1f812b8409f283e5
parentea93f0f19abb82825dab4fcd3f4f40ba35a36b29 (diff)
parenta5b595082859007405aa5158aa86ac3eee00984f (diff)
Merge up to jdk8u20-b16
-rw-r--r--.hgtags20
-rw-r--r--README9
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java4
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java6
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java282
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java12
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java4
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java10
-rw-r--r--buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java9
-rw-r--r--make/BuildNashorn.gmk2
-rw-r--r--make/build.xml25
-rw-r--r--make/project.properties7
-rw-r--r--samples/BufferArray.java110
-rw-r--r--samples/CastExample.java38
-rw-r--r--samples/README1
-rw-r--r--samples/array_mapreduce.js78
-rw-r--r--samples/astviewer.js98
-rw-r--r--samples/barchart_weather.js116
-rw-r--r--samples/call_lambda.js45
-rw-r--r--samples/counters.js10
-rw-r--r--samples/dirname.js36
-rw-r--r--samples/disassemble.js75
-rw-r--r--samples/engine/README1
-rw-r--r--samples/engine/accessvar.js44
-rw-r--r--samples/engine/callfunc.js48
-rw-r--r--samples/engine/callmethod.js64
-rw-r--r--samples/engine/exposevar.js44
-rw-r--r--samples/engine/foreignobject.js71
-rw-r--r--samples/engine/hello.js41
-rw-r--r--samples/engine/interface.js60
-rw-r--r--samples/engine/interface2.js63
-rw-r--r--samples/engine/lambda_as_func.js49
-rw-r--r--samples/env.js43
-rw-r--r--samples/expression_closure.js41
-rw-r--r--samples/fileline.js37
-rw-r--r--samples/fizzbuzz.js48
-rw-r--r--samples/for_each.js66
-rw-r--r--samples/gaussian_random.js46
-rw-r--r--samples/gaussian_random_bind.js48
-rw-r--r--samples/gutenberg.js142
-rw-r--r--samples/heredoc.js51
-rw-r--r--samples/interface_impl.js48
-rw-r--r--samples/javaastviewer.js202
-rw-r--r--samples/javacastcounter.js107
-rw-r--r--samples/javaimporter.js63
-rw-r--r--samples/javalist.js63
-rw-r--r--samples/javamap.js58
-rw-r--r--samples/javashell.js146
-rw-r--r--samples/jsadapter_dom.js189
-rw-r--r--samples/jsobject.js75
-rw-r--r--samples/jsobject_mapreduce.js62
-rw-r--r--samples/jsonviewer.js120
-rw-r--r--samples/letter.js2
-rw-r--r--samples/list_mapreduce.js86
-rw-r--r--samples/locales.js58
-rw-r--r--samples/logisticmap.js82
-rw-r--r--samples/options.js37
-rw-r--r--samples/readLine.js38
-rw-r--r--samples/sam_function.js51
-rw-r--r--samples/shell.js59
-rw-r--r--samples/stack.js55
-rw-r--r--samples/test.js1
-rw-r--r--samples/uniform_random.js49
-rw-r--r--samples/uniq.js39
-rw-r--r--samples/uniqs.js48
-rw-r--r--samples/weather.js63
-rw-r--r--src/jdk/internal/dynalink/beans/BeanLinker.java2
-rw-r--r--src/jdk/nashorn/api/scripting/NashornException.java82
-rw-r--r--src/jdk/nashorn/api/scripting/NashornScriptEngine.java171
-rw-r--r--src/jdk/nashorn/api/scripting/ScriptObjectMirror.java48
-rw-r--r--src/jdk/nashorn/internal/codegen/Attr.java9
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGenerator.java15
-rw-r--r--src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java4
-rw-r--r--src/jdk/nashorn/internal/codegen/Compiler.java42
-rw-r--r--src/jdk/nashorn/internal/codegen/CompilerConstants.java20
-rw-r--r--src/jdk/nashorn/internal/codegen/ConstantData.java49
-rw-r--r--src/jdk/nashorn/internal/codegen/MapCreator.java4
-rw-r--r--src/jdk/nashorn/internal/codegen/MethodEmitter.java6
-rw-r--r--src/jdk/nashorn/internal/codegen/SharedScopeCall.java2
-rw-r--r--src/jdk/nashorn/internal/codegen/types/Type.java2
-rw-r--r--src/jdk/nashorn/internal/ir/FunctionNode.java80
-rw-r--r--src/jdk/nashorn/internal/ir/debug/JSONWriter.java4
-rw-r--r--src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java18
-rw-r--r--src/jdk/nashorn/internal/objects/ArrayBufferView.java8
-rw-r--r--src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java19
-rw-r--r--src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java23
-rw-r--r--src/jdk/nashorn/internal/objects/Global.java492
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArguments.java6
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArray.java60
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArrayBuffer.java23
-rw-r--r--src/jdk/nashorn/internal/objects/NativeBoolean.java27
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDataView.java1015
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDate.java111
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDebug.java19
-rw-r--r--src/jdk/nashorn/internal/objects/NativeError.java62
-rw-r--r--src/jdk/nashorn/internal/objects/NativeEvalError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat32Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFloat64Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFunction.java15
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt16Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt32Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeInt8Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJSAdapter.java20
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJava.java4
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJavaImporter.java13
-rw-r--r--src/jdk/nashorn/internal/objects/NativeMath.java36
-rw-r--r--src/jdk/nashorn/internal/objects/NativeNumber.java37
-rw-r--r--src/jdk/nashorn/internal/objects/NativeObject.java52
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRangeError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeReferenceError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExp.java32
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java6
-rw-r--r--src/jdk/nashorn/internal/objects/NativeStrictArguments.java6
-rw-r--r--src/jdk/nashorn/internal/objects/NativeString.java87
-rw-r--r--src/jdk/nashorn/internal/objects/NativeSyntaxError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeTypeError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeURIError.java16
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint16Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint32Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8Array.java8
-rw-r--r--src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java17
-rw-r--r--src/jdk/nashorn/internal/objects/PrototypeObject.java9
-rw-r--r--src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java74
-rw-r--r--src/jdk/nashorn/internal/parser/AbstractParser.java29
-rw-r--r--src/jdk/nashorn/internal/parser/Lexer.java11
-rw-r--r--src/jdk/nashorn/internal/parser/Parser.java49
-rw-r--r--src/jdk/nashorn/internal/parser/TokenType.java14
-rw-r--r--src/jdk/nashorn/internal/runtime/AccessorProperty.java50
-rw-r--r--src/jdk/nashorn/internal/runtime/CodeInstaller.java12
-rw-r--r--src/jdk/nashorn/internal/runtime/CodeStore.java179
-rw-r--r--src/jdk/nashorn/internal/runtime/CompiledScript.java127
-rw-r--r--src/jdk/nashorn/internal/runtime/Context.java393
-rw-r--r--src/jdk/nashorn/internal/runtime/DebuggerSupport.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/ECMAErrors.java60
-rw-r--r--src/jdk/nashorn/internal/runtime/ECMAException.java46
-rw-r--r--src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java30
-rw-r--r--src/jdk/nashorn/internal/runtime/FindProperty.java17
-rw-r--r--src/jdk/nashorn/internal/runtime/GlobalObject.java244
-rw-r--r--src/jdk/nashorn/internal/runtime/JSONFunctions.java26
-rw-r--r--src/jdk/nashorn/internal/runtime/JSType.java13
-rw-r--r--src/jdk/nashorn/internal/runtime/ListAdapter.java13
-rw-r--r--src/jdk/nashorn/internal/runtime/NativeJavaPackage.java40
-rw-r--r--src/jdk/nashorn/internal/runtime/ParserException.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/Property.java28
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyDescriptor.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyListener.java66
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyListenerManager.java179
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyListeners.java222
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyMap.java409
-rw-r--r--src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java194
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptEnvironment.java8
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptFunction.java59
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptFunctionData.java93
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptLoader.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptObject.java309
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptRuntime.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/SetMethodCreator.java31
-rw-r--r--src/jdk/nashorn/internal/runtime/Source.java475
-rw-r--r--src/jdk/nashorn/internal/runtime/UserAccessorProperty.java10
-rw-r--r--src/jdk/nashorn/internal/runtime/WithObject.java23
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayData.java15
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java204
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java43
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java6
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornGuards.java79
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java25
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java3
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java12
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java12
-rw-r--r--src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java14
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Messages.properties5
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Options.properties15
-rw-r--r--src/jdk/nashorn/internal/scripts/JO.java2
-rw-r--r--src/jdk/nashorn/tools/Shell.java30
-rw-r--r--test/script/basic/JDK-8008448.js1
-rw-r--r--test/script/basic/JDK-8011964.js60
-rw-r--r--test/script/basic/JDK-8011964.js.EXPECTED20
-rw-r--r--test/script/basic/JDK-8024120.js4
-rw-r--r--test/script/basic/JDK-8024174.js2
-rw-r--r--test/script/basic/JDK-8025515.js22
-rw-r--r--test/script/basic/JDK-8026161.js6
-rw-r--r--test/script/basic/JDK-8026161.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8027933.js38
-rw-r--r--test/script/basic/JDK-8027933.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8029364.js49
-rw-r--r--test/script/basic/JDK-8029364.js.EXPECTED7
-rw-r--r--test/script/basic/JDK-8029667.js91
-rw-r--r--test/script/basic/JDK-8029667.js.EXPECTED8
-rw-r--r--test/script/basic/JDK-8030182.js46
-rw-r--r--test/script/basic/JDK-8030182.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8030182_2.js46
-rw-r--r--test/script/basic/JDK-8030182_2.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8030197.js46
-rw-r--r--test/script/basic/JDK-8030199.js50
-rw-r--r--test/script/basic/JDK-8030199.js.EXPECTED14
-rw-r--r--test/script/basic/JDK-8030200.js36
-rw-r--r--test/script/basic/JDK-8030200.js.EXPECTED3
-rw-r--r--test/script/basic/JDK-8030809.js41
-rw-r--r--test/script/basic/JDK-8030809.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8031317.js41
-rw-r--r--test/script/basic/JDK-8031317.js.EXPECTED2
-rw-r--r--test/script/basic/JDK-8031359.js62
-rw-r--r--test/script/basic/JDK-8031359.js.EXPECTED6
-rw-r--r--test/script/basic/JDK-8031715.js49
-rw-r--r--test/script/basic/JDK-8031715.js.EXPECTED11
-rw-r--r--test/script/basic/JDK-8031983.js55
-rw-r--r--test/script/basic/JDK-8031983.js.EXPECTED9
-rw-r--r--test/script/basic/JDK-8032004.js43
-rw-r--r--test/script/basic/JDK-8032068.js56
-rw-r--r--test/script/basic/JDK-8032068.js.EXPECTED14
-rw-r--r--test/script/basic/JDK-8034055.js55
-rw-r--r--test/script/basic/JDK-8034055.js.EXPECTED16
-rw-r--r--test/script/basic/JDK-8037562.js41
-rw-r--r--test/script/basic/JDK-8037562.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8039387.js39
-rw-r--r--test/script/basic/JDK-8039387.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8041998.js52
-rw-r--r--test/script/basic/JDK-8041998.js.EXPECTED4
-rw-r--r--test/script/basic/JDK-8042364.js65
-rw-r--r--test/script/basic/JDK-8042364.js.EXPECTED5
-rw-r--r--test/script/basic/NASHORN-111.js.EXPECTED2
-rw-r--r--test/script/basic/NASHORN-173.js.EXPECTED2
-rw-r--r--test/script/basic/NASHORN-441.js.EXPECTED2
-rw-r--r--test/script/basic/dataview_endian.js70
-rw-r--r--test/script/basic/dataview_getset.js93
-rw-r--r--test/script/basic/dataview_new.js71
-rw-r--r--test/script/basic/list.js2
-rw-r--r--test/script/basic/list.js.EXPECTED2
-rw-r--r--test/script/currently-failing/gettersetter.js48
-rw-r--r--test/script/error/JDK-8027933.js31
-rw-r--r--test/script/error/JDK-8027933.js.EXPECTED3
-rw-r--r--test/script/error/JDK-8039047.js35
-rw-r--r--test/script/error/JDK-8039047.js.EXPECTED6
-rw-r--r--test/script/maptests/builtins.js58
-rw-r--r--test/script/maptests/constructor.js36
-rw-r--r--test/script/maptests/maputil.js38
-rw-r--r--test/script/maptests/object_create.js40
-rw-r--r--test/script/maptests/object_literals.js46
-rw-r--r--test/script/maptests/point.js49
-rw-r--r--test/script/maptests/property_add.js46
-rw-r--r--test/script/maptests/property_delete.js48
-rw-r--r--test/script/maptests/proto.js56
-rw-r--r--test/script/sandbox/JDK-8031106.js39
-rw-r--r--test/script/sandbox/safeprops.js65
-rw-r--r--test/script/trusted/JDK-8006529.js4
-rw-r--r--test/script/trusted/JDK-8032060.js72
-rw-r--r--test/src/jdk/nashorn/api/scripting/InvocableTest.java13
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScopeTest.java316
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java41
-rw-r--r--test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java24
-rw-r--r--test/src/jdk/nashorn/api/scripting/resources/func.js42
-rw-r--r--test/src/jdk/nashorn/api/scripting/resources/gettersetter.js38
-rw-r--r--test/src/jdk/nashorn/api/scripting/resources/witheval.js60
-rw-r--r--test/src/jdk/nashorn/internal/codegen/CompilerTest.java14
-rw-r--r--test/src/jdk/nashorn/internal/parser/ParserTest.java8
-rw-r--r--test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java4
-rw-r--r--test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java159
-rw-r--r--test/src/jdk/nashorn/internal/runtime/ContextTest.java8
-rw-r--r--test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java135
-rw-r--r--test/src/jdk/nashorn/internal/runtime/SourceTest.java128
-rw-r--r--test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java15
-rw-r--r--test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java10
-rw-r--r--test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java36
-rw-r--r--test/src/jdk/nashorn/test/models/SourceHelper.java2
267 files changed, 11554 insertions, 2455 deletions
diff --git a/.hgtags b/.hgtags
index fa8dc451..41dd2043 100644
--- a/.hgtags
+++ b/.hgtags
@@ -236,7 +236,9 @@ c3343930c73c58a22c1d58719bb988aeb25a871f jdk8-b119
32631eed0fad2b31346eb41b29a50227bd29e2ec jdk8-b121
9d112a0e7df737f3b1fa2a021d5bb350ed56c1b7 jdk8-b122
688f4167f92188482b0d80e315c72f726c6d5ff6 jdk8-b123
+0b4301c792254c890811e5b8e32c23338d715928 jdk8u20-b00
7346abe2ea03134e1aee3b3d0fccb047235bd221 jdk8-b124
+d39eb6ab87581becb8efbb5e3a95c99d5e228328 jdk8u20-b01
7346abe2ea03134e1aee3b3d0fccb047235bd221 jdk8-b125
095263db862da23fa04d57c7e93e553831132449 jdk8-b126
fdfbb745caf0e54775a44e66e39d3025785e0528 jdk8-b127
@@ -264,3 +266,21 @@ f0b7b8b5e29a3a4e481fbeb9b346552c9819675e jdk8u5-b08
bc23b19e08eb1575663044902b6442ceaafa924f jdk8u5-b11
18b007062905dac9304605955a4b84eaf2a08553 jdk8u5-b12
e4fb85d69d6b33c9561b932ec5515f44c53c1017 jdk8u5-b13
+43a1183d2ab0ee3dbffd8bc47606e88dbe0c6116 jdk8u20-b02
+9d69311869d513deecfebe767cc5f01502c9c01e jdk8u20-b03
+e70dd55986e085185d976f2a78843a7d7eb87afd jdk8u20-b04
+4ceb9789a6a57bef69b2c7391ac16ea27b6c4f93 jdk8u20-b05
+f87eba70e9ee96255137c389db7cb4e2480e53e7 jdk8-b130
+cca9748cfec7025ac0ddcdede9e5724fa676ad13 jdk8-b131
+5dbdae28a6f3dae3913b118c128bcb1f803317ac jdk8-b132
+4268cd11c2411064ac30dee7a668055ce226c268 jdk8u20-b06
+7e89db817ed094766a039762a8061c3a600c7284 jdk8u20-b07
+2282c86cb1a954efd2fc5b7f22c173be19087c55 jdk8u20-b08
+41f588adeb7a397d395233f00bd3402d0989934a jdk8u20-b09
+fdcdffd5b5b1eb7d442096433d17466f023207f1 jdk8u20-b10
+c116e9229e096ffe841f2b4f79067378288d0d1d jdk8u20-b11
+c720454d2435be052fd941a789ece9468d1e8f74 jdk8u20-b12
+2ca464cf3093444f73e27ace78993629d2f15cb9 jdk8u20-b13
+2f6add5fefb37cfeeb9a7745e7144f0b6d96bbea jdk8u20-b14
+bb2d116675479fb2c9deaeeab6d4c41d41060693 jdk8u20-b15
+c89a4945404ce80e26cb94c90fc13adad6b114bf jdk8u20-b16
diff --git a/README b/README
index 52b30919..242d6077 100644
--- a/README
+++ b/README
@@ -81,13 +81,13 @@ TestNG library and placing its jar file into the lib subdirectory:
After that, you can run the tests using:
cd make
- ant test
+ ant clean test
You can also run the ECMA-262 test suite with Nashorn. In order to do
that, you will need to get a copy of it and put it in
test/script/external/test262 directory. A convenient way to do it is:
- hg clone http://hg.ecmascript.org/tests/test262/ test/script/external/test262
+ git clone https://github.com/tc39/test262 test/script/external/test262
Alternatively, you can check it out elsewhere and make
test/script/external/test262 a symbolic link to that directory. After
@@ -95,6 +95,11 @@ you've done this, you can run the ECMA-262 tests using:
cd nashorn~jdk8/nashorn/make
ant test262
+
+Ant target to get/update external test suites:
+
+ ant externals
+ ant update-externals
These tests take time, so we have a parallelized runner for them that
takes advantage of all processor cores on the computer:
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index 69c28b29..bb6abbc0 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -50,8 +50,6 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE
import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_SETISSHARED_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
@@ -191,8 +189,6 @@ public class ClassGenerator {
// stack: Collection
// pmap = PropertyMap.newMap(Collection<Property>);
mi.invokeStatic(PROPERTYMAP_TYPE, PROPERTYMAP_NEWMAP, PROPERTYMAP_NEWMAP_DESC);
- // pmap.setIsShared();
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_SETISSHARED, PROPERTYMAP_SETISSHARED_DESC);
// $nasgenmap$ = pmap;
mi.putStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
mi.returnVoid();
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
index d46f78c4..67cbde44 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
@@ -33,10 +33,7 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFF
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC;
@@ -171,9 +168,6 @@ public class ConstructorGenerator extends ClassGenerator {
private void loadMap(final MethodGenerator mi) {
if (memberCount > 0) {
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
- // make sure we use duplicated PropertyMap so that original map
- // stays intact and so can be used for many globals.
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
}
}
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index 3fdd7c68..e47f8b16 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -22,40 +22,62 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
package jdk.nashorn.internal.tools.nasgen;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.STRING_DESC;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* Details about a Java method or field annotated with any of the field/method
* annotations from the jdk.nashorn.internal.objects.annotations package.
*/
public final class MemberInfo implements Cloneable {
+ // class loader of this class
+ private static ClassLoader myLoader = MemberInfo.class.getClassLoader();
+
/**
* The different kinds of available class annotations
*/
public static enum Kind {
- /** This is a script class */
+
+ /**
+ * This is a script class
+ */
SCRIPT_CLASS,
- /** This is a constructor */
+ /**
+ * This is a constructor
+ */
CONSTRUCTOR,
- /** This is a function */
+ /**
+ * This is a function
+ */
FUNCTION,
- /** This is a getter */
+ /**
+ * This is a getter
+ */
GETTER,
- /** This is a setter */
+ /**
+ * This is a setter
+ */
SETTER,
- /** This is a property */
+ /**
+ * This is a property
+ */
PROPERTY,
- /** This is a specialized version of a function */
+ /**
+ * This is a specialized version of a function
+ */
SPECIALIZED_FUNCTION,
- /** This is a specialized version of a constructor */
+ /**
+ * This is a specialized version of a constructor
+ */
SPECIALIZED_CONSTRUCTOR
}
@@ -194,6 +216,7 @@ public final class MemberInfo implements Cloneable {
/**
* Check whether this MemberInfo is a getter that resides in the instance
+ *
* @return true if instance setter
*/
boolean isInstanceSetter() {
@@ -245,96 +268,201 @@ public final class MemberInfo implements Cloneable {
}
void verify() {
- if (kind == Kind.CONSTRUCTOR) {
- final Type returnType = Type.getReturnType(javaDesc);
- if (! returnType.toString().equals(OBJECT_DESC)) {
- error("return value should be of Object type, found" + returnType);
- }
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length < 2) {
- error("constructor methods should have at least 2 args");
- }
- if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) {
- error("first argument should be of boolean type, found" + argTypes[0]);
- }
- if (! argTypes[1].toString().equals(OBJECT_DESC)) {
- error("second argument should be of Object type, found" + argTypes[0]);
- }
+ switch (kind) {
+ case CONSTRUCTOR: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJSObjectType(returnType)) {
+ error("return value of a @Constructor method should be of Object type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length < 2) {
+ error("@Constructor methods should have at least 2 args");
+ }
+ if (!argTypes[0].equals(Type.BOOLEAN_TYPE)) {
+ error("first argument of a @Constructor method should be of boolean type, found " + argTypes[0]);
+ }
+ if (!isJavaLangObject(argTypes[1])) {
+ error("second argument of a @Constructor method should be of Object type, found " + argTypes[0]);
+ }
- if (argTypes.length > 2) {
- for (int i = 2; i < argTypes.length - 1; i++) {
- if (! argTypes[i].toString().equals(OBJECT_DESC)) {
- error(i + "'th argument should be of Object type, found " + argTypes[i]);
+ if (argTypes.length > 2) {
+ for (int i = 2; i < argTypes.length - 1; i++) {
+ if (!isJavaLangObject(argTypes[i])) {
+ error(i + "'th argument of a @Constructor method should be of Object type, found " + argTypes[i]);
+ }
}
- }
- final String lastArgType = argTypes[argTypes.length - 1].toString();
- final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
- if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
- error("last argument is neither Object nor Object[] type: " + lastArgType);
- }
+ final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+ final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+ if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+ error("last argument of a @Constructor method is neither Object nor Object[] type: " + lastArgTypeDesc);
+ }
- if (isVarArg && argTypes.length > 3) {
- error("vararg constructor has more than 3 arguments");
+ if (isVarArg && argTypes.length > 3) {
+ error("vararg of a @Constructor method has more than 3 arguments");
+ }
}
}
- } else if (kind == Kind.FUNCTION) {
- final Type returnType = Type.getReturnType(javaDesc);
- if (! returnType.toString().equals(OBJECT_DESC)) {
- error("return value should be of Object type, found" + returnType);
- }
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length < 1) {
- error("function methods should have at least 1 arg");
- }
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument should be of Object type, found" + argTypes[0]);
+ break;
+ case SPECIALIZED_CONSTRUCTOR: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJSObjectType(returnType)) {
+ error("return value of a @SpecializedConstructor method should be a valid JS type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ for (int i = 0; i < argTypes.length; i++) {
+ if (!isValidJSType(argTypes[i])) {
+ error(i + "'th argument of a @SpecializedConstructor method is not valid JS type, found " + argTypes[i]);
+ }
+ }
}
+ break;
+ case FUNCTION: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isValidJSType(returnType)) {
+ error("return value of a @Function method should be a valid JS type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length < 1) {
+ error("@Function methods should have at least 1 arg");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Function method should be of Object type, found " + argTypes[0]);
+ }
- if (argTypes.length > 1) {
- for (int i = 1; i < argTypes.length - 1; i++) {
- if (! argTypes[i].toString().equals(OBJECT_DESC)) {
- error(i + "'th argument should be of Object type, found " + argTypes[i]);
+ if (argTypes.length > 1) {
+ for (int i = 1; i < argTypes.length - 1; i++) {
+ if (!isJavaLangObject(argTypes[i])) {
+ error(i + "'th argument of a @Function method should be of Object type, found " + argTypes[i]);
+ }
}
- }
- final String lastArgType = argTypes[argTypes.length - 1].toString();
- final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC);
- if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) {
- error("last argument is neither Object nor Object[] type: " + lastArgType);
- }
+ final String lastArgTypeDesc = argTypes[argTypes.length - 1].getDescriptor();
+ final boolean isVarArg = lastArgTypeDesc.equals(OBJECT_ARRAY_DESC);
+ if (!lastArgTypeDesc.equals(OBJECT_DESC) && !isVarArg) {
+ error("last argument of a @Function method is neither Object nor Object[] type: " + lastArgTypeDesc);
+ }
- if (isVarArg && argTypes.length > 2) {
- error("vararg function has more than 2 arguments");
+ if (isVarArg && argTypes.length > 2) {
+ error("vararg @Function method has more than 2 arguments");
+ }
}
}
- } else if (kind == Kind.GETTER) {
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length != 1) {
- error("getter methods should have one argument");
- }
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument of getter should be of Object type, found: " + argTypes[0]);
+ break;
+ case SPECIALIZED_FUNCTION: {
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isValidJSType(returnType)) {
+ error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType);
+ }
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ for (int i = 0; i < argTypes.length; i++) {
+ if (!isValidJSType(argTypes[i])) {
+ error(i + "'th argument of a @SpecializedFunction method is not valid JS type, found " + argTypes[i]);
+ }
+ }
}
- if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) {
- error("return type of getter should not be void");
+ break;
+ case GETTER: {
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length != 1) {
+ error("@Getter methods should have one argument");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]);
+ }
+
+ final Type returnType = Type.getReturnType(javaDesc);
+ if (!isJavaLangObject(returnType)) {
+ error("return type of a @Getter method should be Object, found: " + javaDesc);
+ }
}
- } else if (kind == Kind.SETTER) {
- final Type[] argTypes = Type.getArgumentTypes(javaDesc);
- if (argTypes.length != 2) {
- error("setter methods should have two arguments");
+ break;
+ case SETTER: {
+ final Type[] argTypes = Type.getArgumentTypes(javaDesc);
+ if (argTypes.length != 2) {
+ error("@Setter methods should have two arguments");
+ }
+ if (!isJavaLangObject(argTypes[0])) {
+ error("first argument of a @Setter method should be of Object type, found: " + argTypes[0]);
+ }
+ if (!Type.getReturnType(javaDesc).toString().equals("V")) {
+ error("return type of of a @Setter method should be void, found: " + Type.getReturnType(javaDesc));
+ }
}
- if (! argTypes[0].toString().equals(OBJECT_DESC)) {
- error("first argument of setter should be of Object type, found: " + argTypes[0]);
+ break;
+ case PROPERTY: {
+ if (where == Where.CONSTRUCTOR) {
+ if (isStatic()) {
+ if (!isFinal()) {
+ error("static Where.CONSTRUCTOR @Property should be final");
+ }
+
+ if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+ error("static Where.CONSTRUCTOR @Property should be a JS primitive");
+ }
+ }
+ } else if (where == Where.PROTOTYPE) {
+ if (isStatic()) {
+ if (!isFinal()) {
+ error("static Where.PROTOTYPE @Property should be final");
+ }
+
+ if (!isJSPrimitiveType(Type.getType(javaDesc))) {
+ error("static Where.PROTOTYPE @Property should be a JS primitive");
+ }
+ }
+ }
}
- if (!Type.getReturnType(javaDesc).toString().equals("V")) {
- error("return type of setter should be void, found: " + Type.getReturnType(javaDesc));
+ }
+ }
+
+ private static boolean isValidJSType(final Type type) {
+ return isJSPrimitiveType(type) || isJSObjectType(type);
+ }
+
+ private static boolean isJSPrimitiveType(final Type type) {
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.INT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static boolean isJSObjectType(final Type type) {
+ return isJavaLangObject(type) || isJavaLangString(type) || isScriptObject(type);
+ }
+
+ private static boolean isJavaLangObject(final Type type) {
+ return type.getDescriptor().equals(OBJECT_DESC);
+ }
+
+ private static boolean isJavaLangString(final Type type) {
+ return type.getDescriptor().equals(STRING_DESC);
+ }
+
+ private static boolean isScriptObject(final Type type) {
+ if (type.getDescriptor().equals(SCRIPTOBJECT_DESC)) {
+ return true;
+ }
+
+ if (type.getSort() == Type.OBJECT) {
+ try {
+ final Class clazz = Class.forName(type.getClassName(), false, myLoader);
+ return ScriptObject.class.isAssignableFrom(clazz);
+ } catch (final ClassNotFoundException cnfe) {
+ return false;
}
}
+
+ return false;
}
private void error(final String msg) {
- throw new RuntimeException(javaName + javaDesc + " : " + msg);
+ throw new RuntimeException(javaName + " of type " + javaDesc + " : " + msg);
}
/**
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
index 475d7328..479d1d31 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
@@ -349,19 +349,19 @@ public class MethodGenerator extends MethodVisitor {
// invokes, field get/sets
void invokeInterface(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKEINTERFACE, owner, method, desc);
+ super.visitMethodInsn(INVOKEINTERFACE, owner, method, desc, true);
}
void invokeVirtual(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc);
+ super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc, false);
}
void invokeSpecial(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKESPECIAL, owner, method, desc);
+ super.visitMethodInsn(INVOKESPECIAL, owner, method, desc, false);
}
void invokeStatic(final String owner, final String method, final String desc) {
- super.visitMethodInsn(INVOKESTATIC, owner, method, desc);
+ super.visitMethodInsn(INVOKESTATIC, owner, method, desc, false);
}
void putStatic(final String owner, final String field, final String desc) {
@@ -413,7 +413,7 @@ public class MethodGenerator extends MethodVisitor {
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/String;)V");
+ "(Ljava/lang/String;)V", false);
}
// print the object on the top of the stack
@@ -426,6 +426,6 @@ public class MethodGenerator extends MethodVisitor {
super.visitMethodInsn(INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
- "(Ljava/lang/Object;)V");
+ "(Ljava/lang/Object;)V", false);
}
}
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
index 8bb1de5c..7b1fff76 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
@@ -32,10 +32,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.V1_7;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DUPLICATE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX;
@@ -129,7 +126,6 @@ public class PrototypeGenerator extends ClassGenerator {
mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
// make sure we use duplicated PropertyMap so that original map
// stays intact and so can be used for many global.
- mi.invokeVirtual(PROPERTYMAP_TYPE, PROPERTYMAP_DUPLICATE, PROPERTYMAP_DUPLICATE_DESC);
mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
// initialize Function type fields
initFunctionFields(mi);
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
index 72250de7..0ec233ae 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
@@ -146,16 +146,16 @@ public class ScriptClassInstrumentor extends ClassVisitor {
// call $clinit$ just before return from <clinit>
if (isStaticInit && opcode == RETURN) {
super.visitMethodInsn(INVOKESTATIC, scriptClassInfo.getJavaName(),
- $CLINIT$, DEFAULT_INIT_DESC);
+ $CLINIT$, DEFAULT_INIT_DESC, false);
}
super.visitInsn(opcode);
}
@Override
- public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
if (isConstructor && opcode == INVOKESPECIAL &&
INIT.equals(name) && SCRIPTOBJECT_TYPE.equals(owner)) {
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, false);
if (memberCount > 0) {
// initialize @Property fields if needed
@@ -166,7 +166,7 @@ public class ScriptClassInstrumentor extends ClassVisitor {
super.visitTypeInsn(NEW, clazz);
super.visitInsn(DUP);
super.visitMethodInsn(INVOKESPECIAL, clazz,
- INIT, DEFAULT_INIT_DESC);
+ INIT, DEFAULT_INIT_DESC, false);
super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(),
memInfo.getJavaName(), memInfo.getJavaDesc());
}
@@ -180,7 +180,7 @@ public class ScriptClassInstrumentor extends ClassVisitor {
}
}
} else {
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index c4c1ab8d..1d724187 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -45,11 +45,9 @@ import jdk.nashorn.internal.runtime.ScriptObject;
@SuppressWarnings("javadoc")
public interface StringConstants {
// standard jdk types, methods
- static final Type TYPE_METHOD = Type.getType(Method.class);
static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class);
static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class);
static final Type TYPE_OBJECT = Type.getType(Object.class);
- static final Type TYPE_CLASS = Type.getType(Class.class);
static final Type TYPE_STRING = Type.getType(String.class);
static final Type TYPE_COLLECTION = Type.getType(Collection.class);
static final Type TYPE_COLLECTIONS = Type.getType(Collections.class);
@@ -63,6 +61,8 @@ public interface StringConstants {
static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName();
static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName();
static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor();
+ static final String STRING_TYPE = TYPE_STRING.getInternalName();
+ static final String STRING_DESC = TYPE_STRING.getDescriptor();
static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class);
static final String ARRAYLIST_TYPE = TYPE_ARRAYLIST.getInternalName();
static final String COLLECTION_TYPE = TYPE_COLLECTION.getInternalName();
@@ -104,10 +104,6 @@ public interface StringConstants {
static final String PROPERTYMAP_DESC = TYPE_PROPERTYMAP.getDescriptor();
static final String PROPERTYMAP_NEWMAP = "newMap";
static final String PROPERTYMAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_COLLECTION);
- static final String PROPERTYMAP_DUPLICATE = "duplicate";
- static final String PROPERTYMAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
- static final String PROPERTYMAP_SETISSHARED = "setIsShared";
- static final String PROPERTYMAP_SETISSHARED_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP);
// PrototypeObject
static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName();
@@ -135,6 +131,7 @@ public interface StringConstants {
// ScriptObject
static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName();
+ static final String SCRIPTOBJECT_DESC = TYPE_SCRIPTOBJECT.getDescriptor();
static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP);
static final String GETTER_PREFIX = "G$";
diff --git a/make/BuildNashorn.gmk b/make/BuildNashorn.gmk
index fc870442..a987874c 100644
--- a/make/BuildNashorn.gmk
+++ b/make/BuildNashorn.gmk
@@ -77,7 +77,7 @@ $(NASHORN_OUTPUTDIR)/classes/_the.nasgen.run: $(BUILD_NASGEN)
$(RM) -rf $(@D)/jdk $(@D)/netscape
$(CP) -R -p $(NASHORN_OUTPUTDIR)/nashorn_classes/* $(@D)/
$(FIXPATH) $(JAVA) \
- -cp "$(NASHORN_OUTPUTDIR)/nasgen_classes$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes" \
+ -Xbootclasspath/p:"$(NASHORN_OUTPUTDIR)/nasgen_classes$(PATH_SEP)$(NASHORN_OUTPUTDIR)/nashorn_classes" \
jdk.nashorn.internal.tools.nasgen.Main $(@D) jdk.nashorn.internal.objects $(@D)
$(TOUCH) $@
diff --git a/make/build.xml b/make/build.xml
index 7d1f42ae..4d23f228 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -42,6 +42,9 @@
<condition property="hg.executable" value="/usr/local/bin/hg" else="hg">
<available file="/usr/local/bin/hg"/>
</condition>
+ <condition property="git.executable" value="/usr/local/bin/git" else="git">
+ <available file="/usr/local/bin/git"/>
+ </condition>
<!-- check if JDK already has ASM classes -->
<available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/>
<!-- check if testng.jar is avaiable -->
@@ -122,6 +125,7 @@
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-Xlint:deprecation"/>
<compilerarg value="-XDignore.symbol.file"/>
+ <compilerarg value="-Xdiags:verbose"/>
</javac>
<copy todir="${build.classes.dir}/META-INF/services">
<fileset dir="${meta.inf.dir}/services/"/>
@@ -240,6 +244,7 @@
<compilerarg value="-J-Djava.ext.dirs="/>
<compilerarg value="-Xlint:unchecked"/>
<compilerarg value="-Xlint:deprecation"/>
+ <compilerarg value="-Xdiags:verbose"/>
</javac>
<copy todir="${build.test.classes.dir}/META-INF/services">
@@ -250,6 +255,10 @@
<fileset dir="${test.src.dir}/jdk/nashorn/internal/runtime/resources"/>
</copy>
+ <copy todir="${build.test.classes.dir}/jdk/nashorn/api/scripting/resources">
+ <fileset dir="${test.src.dir}/jdk/nashorn/api/scripting/resources"/>
+ </copy>
+
<!-- tests that check nashorn internals and internal API -->
<jar jarfile="${nashorn.internal.tests.jar}">
<fileset dir="${build.test.classes.dir}" excludes="**/api/**"/>
@@ -279,6 +288,11 @@ grant codeBase "file:/${basedir}/test/script/trusted/*" {
permission java.security.AllPermission;
};
+grant codeBase "file:/${basedir}/test/script/maptests/*" {
+ permission java.io.FilePermission "${basedir}/test/script/maptests/*","read";
+ permission java.lang.RuntimePermission "nashorn.debugMode";
+};
+
grant codeBase "file:/${basedir}/test/script/basic/*" {
permission java.io.FilePermission "${basedir}/test/script/-", "read";
permission java.io.FilePermission "$${user.dir}", "read";
@@ -459,18 +473,17 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" {
<!-- test262 test suite -->
<target name="get-test262" depends="init" unless="${test-sys-prop.external.test262}">
- <!-- clone test262 mercurial repo -->
- <exec executable="${hg.executable}">
+ <!-- clone test262 git repo -->
+ <exec executable="${git.executable}">
<arg value="clone"/>
- <arg value="http://hg.ecmascript.org/tests/test262"/>
+ <arg value="https://github.com/tc39/test262"/>
<arg value="${test.external.dir}/test262"/>
</exec>
</target>
<target name="update-test262" depends="init" if="${test-sys-prop.external.test262}">
- <!-- update test262 mercurial repo -->
- <exec executable="${hg.executable}" dir="${test.external.dir}/test262">
+ <!-- update test262 git repo -->
+ <exec executable="${git.executable}" dir="${test.external.dir}/test262">
<arg value="pull"/>
- <arg value="-u"/>
</exec>
</target>
diff --git a/make/project.properties b/make/project.properties
index c3ffca4e..8c5dd4f4 100644
--- a/make/project.properties
+++ b/make/project.properties
@@ -112,6 +112,7 @@ run.classpath=\
test.dir=test
test.script.dir=test/script
test.basic.dir=test/script/basic
+test.maptests.dir=test/script/maptests
test.error.dir=test/script/error
test.sandbox.dir=test/script/sandbox
test.trusted.dir=test/script/trusted
@@ -121,7 +122,7 @@ test262.suite.dir=${test262.dir}/test/suite
testjfx.dir=${test.script.dir}/jfx
test-sys-prop.test.dir=${test.dir}
-test-sys-prop.test.js.roots=${test.basic.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
+test-sys-prop.test.js.roots=${test.basic.dir} ${test.maptests.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
test-sys-prop.test262.suite.dir=${test262.suite.dir}
test-sys-prop.es5conform.testcases.dir=${test.external.dir}/ES5Conform/TestCases
test-sys-prop.test.basic.dir=${test.basic.dir}
@@ -201,7 +202,7 @@ test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests
# test262 test frameworks
test262-test-sys-prop.test.js.framework=\
- --class-cache-size=0 \
+ --class-cache-size=10 \
--no-java \
--no-typed-arrays \
-timezone=PST \
@@ -264,7 +265,7 @@ run.test.jvmargs.octane.main=${run.test.jvmargs.common}
run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
# VM options for script tests with @fork option
-test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}
+test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath}
# path of rhino.jar for benchmarks
rhino.jar=
diff --git a/samples/BufferArray.java b/samples/BufferArray.java
new file mode 100644
index 00000000..00d66023
--- /dev/null
+++ b/samples/BufferArray.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import java.nio.DoubleBuffer;
+
+/**
+ * Simple class demonstrating pluggable script object
+ * implementation. By implementing jdk.nashorn.api.scripting.JSObject
+ * (or extending AbstractJSObject which implements it), you
+ * can supply a friendly script object. Nashorn will call
+ * 'magic' methods on such a class on 'obj.foo, obj.foo = 33,
+ * obj.bar()' etc. from script.
+ *
+ * In this example, Java nio DoubleBuffer object is wrapped
+ * as a friendly script object that provides indexed acces
+ * to buffer content and also support array-like "length"
+ * readonly property to retrieve buffer's capacity. This class
+ * also demonstrates a function valued property called "buf".
+ * On 'buf' method, we return the underlying nio buffer object
+ * that is being wrapped.
+ */
+public class BufferArray extends AbstractJSObject {
+ // underlying nio buffer
+ private final DoubleBuffer buf;
+
+ public BufferArray(int size) {
+ buf = DoubleBuffer.allocate(size);
+ }
+
+ public BufferArray(DoubleBuffer buf) {
+ this.buf = buf;
+ }
+
+ // called to check if indexed property exists
+ @Override
+ public boolean hasSlot(int index) {
+ return index > 0 && index < buf.capacity();
+ }
+
+ // get the value from that index
+ @Override
+ public Object getSlot(int index) {
+ return buf.get(index);
+ }
+
+ // set the value at that index
+ @Override
+ public void setSlot(int index, Object value) {
+ buf.put(index, ((Number)value).doubleValue());
+ }
+
+ // do you have a property of that given name?
+ @Override
+ public boolean hasMember(String name) {
+ return "length".equals(name) || "buf".equals(name);
+ }
+
+ // get the value of that named property
+ @Override
+ public Object getMember(String name) {
+ switch (name) {
+ case "length":
+ return buf.capacity();
+ case "buf":
+ // return a 'function' value for this property
+ return new AbstractJSObject() {
+ @Override
+ public Object call(Object thiz, Object... args) {
+ return BufferArray.this.buf;
+ }
+
+ // yes, I'm a function !
+ @Override
+ public boolean isFunction() {
+ return true;
+ }
+ };
+ }
+ return null;
+ }
+}
diff --git a/samples/CastExample.java b/samples/CastExample.java
new file mode 100644
index 00000000..d876498d
--- /dev/null
+++ b/samples/CastExample.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple java example with type casts.
+// see javacastcounter.js.
+
+class CastExample {
+ public final static int I = (int)23.33;
+ public final String str = (String)"hello";
+}
diff --git a/samples/README b/samples/README
new file mode 100644
index 00000000..7dc23299
--- /dev/null
+++ b/samples/README
@@ -0,0 +1 @@
+Simple Nashorn examples that can be run with "jjs" tool.
diff --git a/samples/array_mapreduce.js b/samples/array_mapreduce.js
new file mode 100644
index 00000000..5335f35d
--- /dev/null
+++ b/samples/array_mapreduce.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Usage: jjs array_mapreduce.js
+
+// Many Array.prototype functions such as map,
+// filter, reduce, reduceRight, every, some are generic.
+// These functions accept ECMAScript array as well as
+// many array-like objects including java arrays.
+// So, you can do map/filter/reduce with Java streams or
+// you can also use Array.prototype functions as below.
+// See also http://en.wikipedia.org/wiki/MapReduce
+
+var DoubleArray = Java.type("double[]");
+var StringArray = Java.type("java.lang.String[]");
+
+var map = Array.prototype.map;
+var filter = Array.prototype.filter;
+var reduce = Array.prototype.reduce;
+
+var jarr = new StringArray(5);
+jarr[0] = "nashorn";
+jarr[1] = "ecmascript";
+jarr[2] = "javascript";
+jarr[3] = "js";
+jarr[4] = "scheme";
+
+// sum of word lengths
+print("Sum word length:",
+ reduce.call(
+ map.call(jarr, function(x) x.length),
+ function(x, y) x + y)
+);
+
+// another array example involving numbers
+jarr = new DoubleArray(10);
+// make random array of numbers
+for (var i = 0; i < jarr.length; i++)
+ jarr[i] = Math.random();
+
+var forEach = Array.prototype.forEach;
+// print numbers in the array
+forEach.call(jarr, function(x) print(x));
+
+// print sum of squares of the random numbers
+print("Square sum:",
+ reduce.call(
+ map.call(jarr, function(x) x*x),
+ function(x, y) x + y)
+);
diff --git a/samples/astviewer.js b/samples/astviewer.js
new file mode 100644
index 00000000..090e50ee
--- /dev/null
+++ b/samples/astviewer.js
@@ -0,0 +1,98 @@
+#// Usage: jjs -scripting -fx astviewer.js -- <scriptfile>
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+if (!$OPTIONS._fx) {
+ print("Usage: jjs -scripting -fx astviewer.js -- <.js file>");
+ exit(1);
+}
+
+// Using JavaFX from Nashorn. See also:
+// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html
+
+// This example shows AST of a script file as a JavaFX
+// tree view in a window. If no file is specified, AST of
+// this script file is shown. This script demonstrates
+// 'load' function, JavaFX support by -fx, readFully function
+// in scripting mode.
+
+// JavaFX classes used
+var StackPane = Java.type("javafx.scene.layout.StackPane");
+var Scene = Java.type("javafx.scene.Scene");
+var TreeItem = Java.type("javafx.scene.control.TreeItem");
+var TreeView = Java.type("javafx.scene.control.TreeView");
+
+// Create a javafx TreeItem to view a AST node
+function treeItemForASTNode(ast, name) {
+ var item = new TreeItem(name);
+ for (var prop in ast) {
+ var node = ast[prop];
+ if (typeof node == 'object') {
+ if (node == null) {
+ // skip nulls
+ continue;
+ }
+
+ if (Array.isArray(node) && node.length == 0) {
+ // skip empty arrays
+ continue;
+ }
+
+ var subitem = treeItemForASTNode(node, prop);
+ } else {
+ var subitem = new TreeItem(prop + ": " + node);
+ }
+ item.children.add(subitem);
+ }
+ return item;
+}
+
+// do we have a script file passed? if not, use current script
+var sourceName = arguments.length == 0? __FILE__ : arguments[0];
+
+// load parser.js from nashorn resources
+load("nashorn:parser.js");
+
+// read the full content of the file and parse it
+// to get AST of the script specified
+var ast = parse(readFully(sourceName));
+
+// JavaFX start method
+function start(stage) {
+ stage.title = "AST Viewer";
+ var rootItem = treeItemForASTNode(ast, sourceName);
+ var tree = new TreeView(rootItem);
+ var root = new StackPane();
+ root.children.add(tree);
+ stage.scene = new Scene(root, 300, 450);
+ stage.show();
+}
diff --git a/samples/barchart_weather.js b/samples/barchart_weather.js
new file mode 100644
index 00000000..8574f0a2
--- /dev/null
+++ b/samples/barchart_weather.js
@@ -0,0 +1,116 @@
+#// Usage: jjs -fx barchart_weather.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Example that retrieves weather data from a URL in JSON
+// format and draws bar chart using JavaFX
+
+// -fx check
+if (! $OPTIONS._fx) {
+ print("Usage: jjs -fx barchart_weather.js");
+ exit(1);
+}
+
+// Java classes used
+var URL = Java.type("java.net.URL");
+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();
+ }
+}
+
+// change URL for your city here!
+var url = "http://api.openweathermap.org/data/2.5/forecast?q=chennai,india&units=metric&mode=json";
+
+// download JSON document and parse
+var json = readTextFromURL(url);
+var weather = JSON.parse(json);
+
+// View JSON of this using site such as http://www.jsoneditoronline.org/ to know
+// about the JSON data format used by this site
+
+// Extracted data from the json object
+var temp = weather.list.map(function(x) x.main.temp);
+var temp_min = weather.list.map(function(x) x.main.temp_min);
+var temp_max = weather.list.map(function(x) x.main.temp_max);
+var date = weather.list.map(function(x) x.dt_txt);
+
+// JavaFX classes used
+var Scene = Java.type("javafx.scene.Scene");
+var BarChart = Java.type("javafx.scene.chart.BarChart");
+var CategoryAxis = Java.type("javafx.scene.chart.CategoryAxis");
+var NumberAxis = Java.type("javafx.scene.chart.NumberAxis");
+var XYChart = Java.type("javafx.scene.chart.XYChart");
+
+function start(stage) {
+ stage.title="Chennai Weather Bar Chart";
+ var xAxis = new CategoryAxis();
+ xAxis.label = "date/time";
+ var yAxis = new NumberAxis();
+ yAxis.label = "temp in C";
+ var bc = new BarChart(xAxis, yAxis);
+
+ // 3 bars per datetime item - temp, min temp and max temp
+ var s1 = new XYChart.Series();
+ s1.name = "temp";
+ for (d in date) {
+ s1.data.add(new XYChart.Data(date[d], temp[d]));
+ }
+
+ var s2 = new XYChart.Series();
+ s2.name = "min temp";
+ for (d in date) {
+ s2.data.add(new XYChart.Data(date[d], temp_min[d]));
+ }
+
+ var s3 = new XYChart.Series();
+ s3.name = "max temp";
+ for (d in date) {
+ s3.data.add(new XYChart.Data(date[d], temp_max[d]));
+ }
+
+ bc.data.addAll(s1, s2, s3);
+
+ stage.scene = new Scene(bc, 800, 600);
+ stage.show();
+}
diff --git a/samples/call_lambda.js b/samples/call_lambda.js
new file mode 100644
index 00000000..d865164f
--- /dev/null
+++ b/samples/call_lambda.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn allows you treat every Java8 lambda as a function
+
+var JFunction = Java.type("java.util.function.Function");
+var obj = new JFunction() {
+ apply: function(x) {
+ print(x + ", lambda");
+ }
+};
+
+// prints 'function'
+print(typeof obj);
+
+// call it!
+obj("hello");
diff --git a/samples/counters.js b/samples/counters.js
index 226ec3de..d89ad581 100644
--- a/samples/counters.js
+++ b/samples/counters.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -33,7 +33,11 @@
* This file can be run along with any script you want to run
* to print aggregate stat counters from nashorn.
*
- * Usage: jjs <your-file.js> counters.js
+ * Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js
*/
-Debug.dumpCounters();
+if (java.lang.System.getProperty("nashorn.debug") == null) {
+ print("Usage: jjs -J-Dnashorn.debug <your-file.js> counters.js");
+} else {
+ Debug.dumpCounters();
+}
diff --git a/samples/dirname.js b/samples/dirname.js
new file mode 100644
index 00000000..119d4f33
--- /dev/null
+++ b/samples/dirname.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// __DIR__ variable is equivalent of `dirname $0` in
+// shell scripts - expands to the directory where
+// the current script is located.
+
+print("This script is in the directory: " + __DIR__);
diff --git a/samples/disassemble.js b/samples/disassemble.js
new file mode 100644
index 00000000..654b9dd8
--- /dev/null
+++ b/samples/disassemble.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Usage: jjs disassemble.js -- <.class-file-path>
+
+// Simple .class disassembler that uses bundled ObjectWeb ASM
+// classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are
+// not part of official jdk8 API. It can be changed/removed
+// without notice. So, this script is brittle by design!
+
+// This example demonstrates passing arguments to script
+// from jjs command line, nio and ASM usage.
+
+// classes used
+var FileSystems = Java.type("java.nio.file.FileSystems");
+var Files = Java.type("java.nio.file.Files");
+var System = Java.type("java.lang.System");
+var PrintWriter = Java.type("java.io.PrintWriter");
+
+// WARNING: uses non-API classes of jdk8!
+var ClassReader = Java.type("jdk.internal.org.objectweb.asm.ClassReader");
+var TraceClassVisitor = Java.type("jdk.internal.org.objectweb.asm.util.TraceClassVisitor");
+
+// convert file name to Path instance
+function path(file) {
+ return FileSystems.default.getPath(file);
+}
+
+// read all file content as a byte[]
+function readAllBytes(file) {
+ return Files.readAllBytes(path(file));
+}
+
+// disassemble .class byte[] and prints output to stdout
+function disassemble(bytecode) {
+ var pw = new PrintWriter(System.out);
+ new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0);
+}
+
+// check for command line arg (for .class file name)
+if (arguments.length == 0 || !arguments[0].endsWith('.class')) {
+ print("Usage: jjs disassemble -- <.class file>");
+ exit(1);
+}
+
+// disassemble the given .class file
+disassemble(readAllBytes(arguments[0]));
diff --git a/samples/engine/README b/samples/engine/README
new file mode 100644
index 00000000..88584955
--- /dev/null
+++ b/samples/engine/README
@@ -0,0 +1 @@
+Using javax.script engine API of nashorn from script!
diff --git a/samples/engine/accessvar.js b/samples/engine/accessvar.js
new file mode 100644
index 00000000..ae9ec7de
--- /dev/null
+++ b/samples/engine/accessvar.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple example showing global variable access from caller
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code!
+engine.eval("x = 'hello'");
+
+// access global var from engine
+print(engine.get('x'));
diff --git a/samples/engine/callfunc.js b/samples/engine/callfunc.js
new file mode 100644
index 00000000..76108fd1
--- /dev/null
+++ b/samples/engine/callfunc.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// simple example showing how to call a global script
+// function from caller
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code!
+engine.eval("function func(name) { print('I am func, hello ' + name) }");
+
+// invoke functions, methods of code evaluated by engine
+// from javax.script.Invocable interface. But, hey,
+// calling code is JavaScript and don't worry about types :)
+
+engine.invokeFunction("func", "Nashorn");
diff --git a/samples/engine/callmethod.js b/samples/engine/callmethod.js
new file mode 100644
index 00000000..8199dcd6
--- /dev/null
+++ b/samples/engine/callmethod.js
@@ -0,0 +1,64 @@
+#// Usage: jjs -scripting callmethod.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// simple example demonstrating calling a script object
+// method from script engine user code
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code - too many script escapes?
+// use heredoc !
+engine.eval(<<CODE
+ var obj = {
+ func: function() {
+ print("I am func of " + this);
+ },
+
+ toString: function() {
+ return "Object 'obj'";
+ }
+ };
+CODE);
+
+// invoke methods of an object in script world
+// from javax.script.Invocable interface. But, hey,
+// calling code is JavaScript and don't worry about types :)
+
+// get that script object on which to call a method
+var scriptObj = engine.get("obj");
+// call 'func' method on object 'obj'
+engine.invokeMethod(scriptObj, "func");
diff --git a/samples/engine/exposevar.js b/samples/engine/exposevar.js
new file mode 100644
index 00000000..93f57ed8
--- /dev/null
+++ b/samples/engine/exposevar.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Example showing how to expose a script global var from caller
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// expose variable to engine
+engine.put("name", "Nashorn");
+
+// access it from script
+engine.eval("print('Hello, ' + name)");
diff --git a/samples/engine/foreignobject.js b/samples/engine/foreignobject.js
new file mode 100644
index 00000000..3850089d
--- /dev/null
+++ b/samples/engine/foreignobject.js
@@ -0,0 +1,71 @@
+#// Usage: jjs -scripting foreignobject.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// cross nashorn engine scripting
+// access script objects from other engines in natural syntax
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code!
+engine.eval(<<CODE
+ var obj = {
+ foo: 42,
+ func: function() {
+ print("func: " + this.foo);
+ }
+ };
+CODE);
+
+// Nashorn engine returns script objects as instance of
+// the class jdk.nashorn.api.scripting.ScriptObjectMirror
+// But nashorn's dynalink linker can treat these objects
+// specially to support natural script syntax to access..
+// In Java code, you need to use ScriptObjectMirror's
+// methods though. Once again, script world is simpler :-)
+
+var foreignObj = engine.get("obj");
+// access properties, functions of it
+// with natural syntax
+print(foreignObj.foo);
+foreignObj.func();
+print(typeof foreignObj.func);
+
+// access engine's global
+var foreignGlobal = engine.eval("this");
+// create objects in engine's world from here!
+print(new foreignGlobal.Object());
+print(new foreignGlobal.Date());
diff --git a/samples/engine/hello.js b/samples/engine/hello.js
new file mode 100644
index 00000000..37fabbfe
--- /dev/null
+++ b/samples/engine/hello.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple hello world example showing create engine
+// and eval simple script
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+// eval code!
+engine.eval("print('hello world')");
diff --git a/samples/engine/interface.js b/samples/engine/interface.js
new file mode 100644
index 00000000..75b7aa21
--- /dev/null
+++ b/samples/engine/interface.js
@@ -0,0 +1,60 @@
+#// Usage: jjs -scripting interface.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Example demonstrating how to implement a Java interface
+// whose methods are backed by global script functions
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code - too many script escapes?
+// use heredoc !
+engine.eval(<<CODE
+function run() {
+ print("run global function called");
+}
+CODE);
+
+// create Java interface object whose methods are
+// implemented by script functions. This is from
+// javax.script.Invocable. But we are in JS world,
+// don't worry about types :)
+
+var Runnable = Java.type("java.lang.Runnable");
+var r = engine.getInterface(Runnable.class);
+print(r.class);
+
+r.run();
diff --git a/samples/engine/interface2.js b/samples/engine/interface2.js
new file mode 100644
index 00000000..771b1101
--- /dev/null
+++ b/samples/engine/interface2.js
@@ -0,0 +1,63 @@
+#// Usage: jjs -scripting interface2.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple example demonstrating how to implement java interface
+// whose methods are backed by script methods of a script object
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// eval code - too many script escapes?
+// use heredoc !
+engine.eval(<<CODE
+ var obj = {
+ run: function() {
+ print("I am run method of 'obj'");
+ }
+ };
+CODE);
+
+// create Java interface object whose methods are
+// implemented by script methods of a script object
+// This is from javax.script.Invocable. But we are
+// in JS world, don't worry about types :)
+
+var Runnable = Java.type("java.lang.Runnable");
+
+var scriptObj = engine.get("obj");
+var r = engine.getInterface(scriptObj, Runnable.class);
+print(r.class);
+r.run();
diff --git a/samples/engine/lambda_as_func.js b/samples/engine/lambda_as_func.js
new file mode 100644
index 00000000..2600f17a
--- /dev/null
+++ b/samples/engine/lambda_as_func.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple example demonstrating how to expose 'function's
+// from embedding code. Any lambda object exposed to engine
+// can be called as 'function' in script.
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+// create manager
+var manager = new ScriptEngineManager();
+// create engine
+var engine = manager.getEngineByName("js");
+
+// Any lambda (@FunctionalInterface annotated type) object can be
+// be exposed from script embedding code. Script can call
+// it as a function
+engine.put("upper", new java.util.function.Function() {
+ apply: function(x) x.toUpperCase()
+});
+
+print(engine.eval("upper('hello')"));
diff --git a/samples/env.js b/samples/env.js
new file mode 100644
index 00000000..74377ebd
--- /dev/null
+++ b/samples/env.js
@@ -0,0 +1,43 @@
+#// Usage: jjs -scripting env.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// In nashorn -scripting mode,
+// "$ENV" object exposes process
+// environment variables
+
+print($ENV.PATH);
+print($ENV.JAVA_HOME);
+
+for (i in $ENV) {
+ print(i, "->", $ENV[i]);
+}
diff --git a/samples/expression_closure.js b/samples/expression_closure.js
new file mode 100644
index 00000000..1efb1842
--- /dev/null
+++ b/samples/expression_closure.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports expression closures extension of
+// Mozilla JavaScript 1.8. See also
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8
+
+// leave {, } and 'return' keyword
+
+function sqr(x) x*x;
+
+// prints 289 (= 17*17)
+print(sqr(17));
diff --git a/samples/fileline.js b/samples/fileline.js
new file mode 100644
index 00000000..05c99759
--- /dev/null
+++ b/samples/fileline.js
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports pseudo global variables __FILE__
+// and __LINE__ that expands to currently executed
+// script file name and current script line number
+
+// prints current file and line number
+print("executing " + __FILE__ + " @ " + __LINE__);
diff --git a/samples/fizzbuzz.js b/samples/fizzbuzz.js
new file mode 100644
index 00000000..ba8d83d4
--- /dev/null
+++ b/samples/fizzbuzz.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// What is FizzBuzz? http://c2.com/cgi/wiki?FizzBuzzTest
+
+// Yet another FizzBuzz impl. using Java 8 lambda and stream
+// but using Nashorn. This is ECMAScript port of @stuartmarks'
+// Java implementation
+
+var IntStream = Java.type("java.util.stream.IntStream");
+
+function ifmod(m, r, f) {
+ return function(i) { return i % m == 0? r : f(i); }
+}
+
+// pass script function for lambda
+IntStream.rangeClosed(1, 100).
+ mapToObj(
+ ifmod(15, "FizzBuzz", ifmod(5, "Buzz", ifmod(3, "Fizz", String))))
+ .forEach(print);
diff --git a/samples/for_each.js b/samples/for_each.js
new file mode 100644
index 00000000..10fc39a1
--- /dev/null
+++ b/samples/for_each.js
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports for..each extension supported
+// by Mozilla. See also
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for_each...in
+
+var strs = [ "hello", "world" ];
+for each (str in strs)
+ print(str);
+
+// create a java int[] object
+var JArray = Java.type("int[]");
+var arr = new JArray(10);
+
+// store squares as values
+for (i in arr)
+ arr[i] = i*i;
+
+// for .. each on java arrays
+print("squares");
+for each (i in arr)
+ print(i);
+
+var System = Java.type("java.lang.System");
+
+// for..each on java Iterables
+// print System properties as name = value pairs
+print("System properties");
+for each (p in System.properties.entrySet()) {
+ print(p.key, "=", p.value);
+}
+
+// print process environment vars as name = value pairs
+print("Process environment");
+for each (e in System.env.entrySet()) {
+ print(e.key, "=", e.value);
+}
diff --git a/samples/gaussian_random.js b/samples/gaussian_random.js
new file mode 100644
index 00000000..f52f49f3
--- /dev/null
+++ b/samples/gaussian_random.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// print 100 Guassian distributed numbers
+
+var Random = Java.type("java.util.Random");
+var DoubleStream = Java.type("java.util.stream.DoubleStream");
+
+var r = new Random();
+
+// expression closure (see expression_closure.js as well)
+// passed as lambda double generator. "print" passed as
+// double consumer lambda to 'forEach' method.
+
+DoubleStream
+ .generate(function() r.nextGaussian())
+ .limit(100)
+ .forEach(print);
diff --git a/samples/gaussian_random_bind.js b/samples/gaussian_random_bind.js
new file mode 100644
index 00000000..052520cd
--- /dev/null
+++ b/samples/gaussian_random_bind.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// print 100 Guassian distributed numbers
+
+var Random = Java.type("java.util.Random");
+var DoubleStream = Java.type("java.util.stream.DoubleStream");
+
+// function as lambda double generator. "print" passed as
+// double consumer lambda to 'forEach' method.
+// Function.prototype.bind used to attach 'state' for the
+// generator function.
+
+DoubleStream
+ .generate(
+ function(r) {
+ return r.nextGaussian()
+ }.bind(this, new Random()))
+ .limit(100)
+ .forEach(print);
diff --git a/samples/gutenberg.js b/samples/gutenberg.js
new file mode 100644
index 00000000..4d83a573
--- /dev/null
+++ b/samples/gutenberg.js
@@ -0,0 +1,142 @@
+#// Usage: jjs -scripting gutenberg.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple example that demonstrates reading XML Rss feed
+// to generate a HTML file from script and show it by browser
+
+// Java classes used
+var Characters = Java.type("javax.xml.stream.events.Characters");
+var Factory = Java.type("javax.xml.stream.XMLInputFactory");
+var File = Java.type("java.io.File");
+var FileWriter = Java.type("java.io.FileWriter");
+var PrintWriter = Java.type("java.io.PrintWriter");
+var URL = Java.type("java.net.URL");
+
+// read Rss feed from a URL. Returns an array
+// of objects having only title and link properties
+function readRssFeed(url) {
+ var fac = Factory.newInstance();
+ var reader = fac.createXMLEventReader(url.openStream());
+
+ // get text content from next event
+ function getChars() {
+ var result = "";
+ var e = reader.nextEvent();
+ if (e instanceof Characters) {
+ result = e.getData();
+ }
+ return result;
+ }
+
+ var items = [];
+ var title, link;
+ var inItem = false;
+ while (reader.hasNext()) {
+ var evt = reader.nextEvent();
+ if (evt.isStartElement()) {
+ var local = evt.name.localPart;
+ if (local == "item") {
+ // capture title, description now
+ inItem = true;
+ }
+
+ if (inItem) {
+ switch (local) {
+ case 'title':
+ title = getChars();
+ break;
+ case 'link':
+ link = getChars();
+ break;
+ }
+ }
+ } else if (evt.isEndElement()) {
+ var local = evt.name.localPart;
+ if (local == "item") {
+ // one item done, save it in result array
+ items.push({ title: title, link: link });
+ inItem = false;
+ }
+ }
+ }
+
+ return items;
+}
+
+// generate simple HTML for an RSS feed
+function getBooksHtml() {
+ var url = new URL("http://www.gutenberg.org/cache/epub/feeds/today.rss");
+ var items = readRssFeed(url);
+
+ var str = "<ul>";
+
+ // Nashorn's string interpolation and heredoc
+ // support is very handy in generating text content
+ // that is filled with elements from runtime objects.
+ // We insert title and link in <li> elements here.
+ for each (i in items) {
+ str += <<EOF
+<li>
+ <a href="${i.link}">${i.title}</a>
+</li>
+EOF
+ }
+ str += "</ul>";
+ return str;
+}
+
+// write the string to the given file
+function writeTo(file, str) {
+ var w = new PrintWriter(new FileWriter(file));
+ try {
+ w.print(str);
+ } finally {
+ w.close();
+ }
+}
+
+// generate books HTML
+var str = getBooksHtml();
+
+// write to file. __DIR__ is directory where
+// this script is stored.
+var file = new File(__DIR__ + "books.html");
+writeTo(file, str);
+
+// show it by desktop browser
+try {
+ var Desktop = Java.type("java.awt.Desktop");
+ Desktop.desktop.browse(file.toURI());
+} catch (e) {
+ print(e);
+}
diff --git a/samples/heredoc.js b/samples/heredoc.js
new file mode 100644
index 00000000..0c52ca93
--- /dev/null
+++ b/samples/heredoc.js
@@ -0,0 +1,51 @@
+#// Usage: jjs -scripting heredoc.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Nashorn supports Shell script like here-documents
+// in -scripting mode. Here-docs are multi-line strings
+// that are possibly interpolated with ${} expressions
+// See also http://en.wikipedia.org/wiki/Here_document
+
+var sender = "Buffy the Vampire Slayer";
+var recipient = "Spike";
+
+print(<<END
+
+Dear ${recipient},
+
+I wish you to leave Sunnydale and never return.
+
+Not Quite Love,
+${sender}
+
+END);
diff --git a/samples/interface_impl.js b/samples/interface_impl.js
new file mode 100644
index 00000000..5e498166
--- /dev/null
+++ b/samples/interface_impl.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports Java interface implementation
+// by script using anonymous class-like syntax
+
+var Runnable = Java.type("java.lang.Runnable");
+var Thread = Java.type("java.lang.Thread");
+// use anonymous class-like new syntax
+var r = new Runnable() {
+ run: function() {
+ print("I am a runnable " + Thread.currentThread());
+ }
+}
+
+r.run();
+
+var t = new Thread(r);
+t.start();
+t.join();
diff --git a/samples/javaastviewer.js b/samples/javaastviewer.js
new file mode 100644
index 00000000..c446abe5
--- /dev/null
+++ b/samples/javaastviewer.js
@@ -0,0 +1,202 @@
+#// Usage: jjs -fx javaastviewer.js -- <.java files>
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example also uses
+// -fx and javafx TreeView to visualize Java AST as TreeView
+
+if (!$OPTIONS._fx || arguments.length == 0) {
+ print("Usage: jjs -fx javaastviewer.js -- <.java files>");
+ exit(1);
+}
+
+// Java types used
+var Enum = Java.type("java.lang.Enum");
+var HashSet = Java.type("java.util.HashSet");
+var Name = Java.type("javax.lang.model.element.Name");
+var List = Java.type("java.util.List");
+var Set = Java.type("java.util.Set");
+var SimpleTreeVisitor = Java.type("com.sun.source.util.SimpleTreeVisitor");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+
+function javaASTToScriptObject(args) {
+ // properties ignored (javac implementation class properties) in AST view.
+ // may not be exhaustive - any getAbc would become "abc" property or
+ // public field becomes a property of same name.
+ var ignoredProps = new HashSet();
+ for each (var word in
+ ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs',
+ 'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam',
+ 'restype', 'params', 'startPosition', 'thrown',
+ 'tree', 'typarams', 'typetag', 'vartype']) {
+ ignoredProps.add(word);
+ }
+
+ // get the system compiler tool
+ var compiler = ToolProvider.systemJavaCompiler;
+
+ // get standard file manager
+ var fileMgr = compiler.getStandardFileManager(null, null, null);
+
+ // make a list of compilation unit from command line argument file names
+ // Using Java.to convert script array (arguments) to a Java String[]
+ var compUnits = fileMgr.getJavaFileObjects(Java.to(args, StringArray));
+
+ // create a new compilation task
+ var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+
+ // subclass SimpleTreeVisitor - converts Java AST node to
+ // a simple script object by walking through it
+ var ConverterVisitor = Java.extend(SimpleTreeVisitor);
+
+ var visitor = new ConverterVisitor() {
+ // convert java AST node to a friendly script object
+ // which can be viewed. Every node ends up in defaultAction
+ // method of SimpleTreeVisitor method.
+
+ defaultAction: function (node, p) {
+ var resultObj = {};
+ // Nashorn does not iterate properties and methods of Java objects
+ // But, we can bind properties of any object (including java objects)
+ // to a script object and iterate it!
+ var obj = {};
+ Object.bindProperties(obj, node);
+
+ // we don't want every property, method of java object
+ for (var prop in obj) {
+ var val = obj[prop];
+ var type = typeof val;
+ // ignore 'method' members
+ if (type == 'function' || type == 'undefined') {
+ continue;
+ }
+
+ // ignore properties from Javac implementation
+ // classes - hack by name!!
+ if (ignoredProps.contains(prop)) {
+ continue;
+ }
+
+ // subtree - recurse it
+ if (val instanceof Tree) {
+ resultObj[prop] = visitor.visit(val, p);
+ } else if (val instanceof List) {
+ // List of trees - recurse each and make an array
+ var len = val.size();
+ if (len != 0) {
+ var arr = [];
+ for (var j = 0; j < len; j++) {
+ var e = val[j];
+ if (e instanceof Tree) {
+ arr.push(visitor.visit(e, p));
+ }
+ }
+ resultObj[prop] = arr;
+ }
+ } else if (val instanceof Set) {
+ // Set - used for modifier flags
+ // make array
+ var len = val.size();
+ if (len != 0) {
+ var arr = [];
+ for each (var e in val) {
+ if (e instanceof Enum || typeof e == 'string') {
+ arr.push(e.toString());
+ }
+ }
+ resultObj[prop] = arr;
+ }
+ } else if (val instanceof Enum || val instanceof Name) {
+ // make string for any Enum or Name
+ resultObj[prop] = val.toString();
+ } else if (type != 'object') {
+ // primitives 'as is'
+ resultObj[prop] = val;
+ }
+ }
+ return resultObj;
+ }
+ }
+
+ // top level object with one property for each compilation unit
+ var scriptObj = {};
+ for each (var cu in task.parse()) {
+ scriptObj[cu.sourceFile.name] = cu.accept(visitor, null);
+ }
+
+ return scriptObj;
+}
+
+// JavaFX classes used
+var StackPane = Java.type("javafx.scene.layout.StackPane");
+var Scene = Java.type("javafx.scene.Scene");
+var TreeItem = Java.type("javafx.scene.control.TreeItem");
+var TreeView = Java.type("javafx.scene.control.TreeView");
+
+// Create a javafx TreeItem to view a script object
+function treeItemForObject(obj, name) {
+ var item = new TreeItem(name);
+ for (var prop in obj) {
+ var node = obj[prop];
+ if (typeof node == 'object') {
+ if (node == null) {
+ // skip nulls
+ continue;
+ }
+ var subitem = treeItemForObject(node, prop);
+ } else {
+ var subitem = new TreeItem(prop + ": " + node);
+ }
+ item.children.add(subitem);
+ }
+
+ item.expanded = true;
+ return item;
+}
+
+var commandArgs = arguments;
+
+// JavaFX start method
+function start(stage) {
+ var obj = javaASTToScriptObject(commandArgs);
+ stage.title = "Java AST Viewer"
+ var rootItem = treeItemForObject(obj, "AST");
+ rootItem.expanded = true;
+ var tree = new TreeView(rootItem);
+ var root = new StackPane();
+ root.children.add(tree);
+ stage.scene = new Scene(root, 300, 450);
+ stage.show();
+}
diff --git a/samples/javacastcounter.js b/samples/javacastcounter.js
new file mode 100644
index 00000000..607b2f82
--- /dev/null
+++ b/samples/javacastcounter.js
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Usage: jjs javacastcounter.js -- <.java files>
+
+// This example demonstrates Nashorn Java.extend API
+// to subclass a Java class from script.
+
+// This example uses Javac Compiler and Tree API
+// to list type casts used in java source files.
+
+if (arguments.length == 0) {
+ print("Usage: jjs javacastcounter.js -- <.java files>");
+ exit(1);
+}
+
+// Java types used
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+var Trees = Java.type("com.sun.source.util.Trees");
+var StringArray = Java.type("java.lang.String[]");
+
+// get the system compiler tool
+var compiler = ToolProvider.systemJavaCompiler;
+
+// get standard file manager
+var fileMgr = compiler.getStandardFileManager(null, null, null);
+
+// make a list of compilation unit from command line argument file names
+// Using Java.to convert script array (arguments) to a Java String[]
+var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray));
+
+// create a new compilation task
+var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+
+// SourcePositions object to get positions of AST nodes
+var sourcePositions = Trees.instance(task).sourcePositions;
+
+// Subclass TreeScanner class
+var CastCounter = Java.extend(TreeScanner);
+
+var counter = new CastCounter() {
+ // current CompilationUnitTree
+ compUnit: null,
+ // current LineMap (pos -> line, column)
+ lineMap: null,
+ // current compilation unit's file name
+ fileName: null,
+
+ // overrides of TreeScanner methods
+
+ visitCompilationUnit: function(node, p) {
+ // capture info about current Compilation unit
+ this.compUnit = node;
+ this.lineMap = node.lineMap;
+ this.fileName = node.sourceFile.name;
+
+ // Using Java.super API to call super class method here
+ return Java.super(counter).visitCompilationUnit(node, p);
+ },
+
+ visitTypeCast: function(node, p) {
+ // print information on this type cast node
+ var pos = sourcePositions.getStartPosition(this.compUnit, node);
+ var line = this.lineMap.getLineNumber(pos);
+ var col = this.lineMap.getColumnNumber(pos);
+ print(node + " @ " + this.fileName + ":" + line + ":" + col);
+
+ // count one more type cast
+ return 1;
+ },
+
+ reduce: function(r1, r2) {
+ return (r1 == null ? 0 : r1) + (r2 == null ? 0 : r2);
+ }
+};
+
+// print total number of type cast nodes seen
+print("Total casts:", counter.scan(task.parse(), null));
diff --git a/samples/javaimporter.js b/samples/javaimporter.js
new file mode 100644
index 00000000..dd487ec1
--- /dev/null
+++ b/samples/javaimporter.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// JavaImporter along with 'with' statement helps in
+// localized Java class references
+
+function readTextFromURL(url) {
+
+ // equivalent to
+ //
+ // import java.io.*;
+ // import java.net.*;
+ // import java.lang.StringBuffer;
+ //
+ // only inside the 'with' statement
+ with (new JavaImporter(java.io,
+ java.net,
+ java.lang.StringBuilder)) {
+ var buf = new StringBuilder();
+ var u = new URL(url);
+ var reader = new BufferedReader(
+ new InputStreamReader(u.openStream()));
+ var line = null;
+ try {
+ while ((line = reader.readLine()) != null)
+ buf.append(line).append('\n');
+ } finally {
+ reader.close();
+ }
+
+ return buf.toString();
+ }
+}
+
+print(readTextFromURL("https://twitter.com/"));
diff --git a/samples/javalist.js b/samples/javalist.js
new file mode 100644
index 00000000..8f3749b5
--- /dev/null
+++ b/samples/javalist.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Java List elements accessed/modified via
+// array element access/update syntax
+
+var ArrayList = Java.type("java.util.ArrayList");
+var list = new ArrayList();
+
+// add elements to list by List's add method calls
+list.add("js");
+list.add("ecmascript");
+list.add("nashorn");
+
+// get by List's get(int) method
+print(list[0]);
+print(list[1]);
+print(list[2]);
+
+// access list elements by indexed access as well
+print(list[0]);
+print(list[1]);
+print(list[2]);
+
+// assign to list elements by index as well
+list[0] = list[0].toUpperCase();
+list[1] = list[1].toUpperCase();
+list[2] = list[2].toUpperCase();
+
+print(list.get(0));
+print(list.get(1));
+print(list.get(2));
+print(list[0]);
+print(list[1]);
+print(list[2]);
diff --git a/samples/javamap.js b/samples/javamap.js
new file mode 100644
index 00000000..a53d0320
--- /dev/null
+++ b/samples/javamap.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Java Map keys as properties
+
+// Demonstrating Java Map key/value can be accessed
+// as property/value from script.
+
+var HashMap = Java.type("java.util.HashMap");
+var map = new HashMap();
+
+// map key-value access by java get/put method calls
+map.put('js', 'nashorn');
+print(map.get('js'));
+
+// access keys of map as properties
+print(map['js']);
+print(map.js);
+
+// also assign new key-value pair
+// as 'property-value'
+map['language'] = 'java';
+print(map.get("language"));
+print(map.language);
+print(map['language']);
+
+map.answer = 42;
+print(map.get("answer"));
+print(map.answer);
+print(map['answer']);
diff --git a/samples/javashell.js b/samples/javashell.js
new file mode 100644
index 00000000..65d1a8a2
--- /dev/null
+++ b/samples/javashell.js
@@ -0,0 +1,146 @@
+#// Usage: jjs -scripting javashell.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple Java "shell" with which you can try out
+// your few liner Java code leaving imports, main etc.
+// And you can leave even compilation as this script
+// takes care boilerplate+compile step for you.
+
+// Java types used
+var Arrays = Java.type("java.util.Arrays");
+var BufferedReader = Java.type("java.io.BufferedReader");
+var FileWriter = Java.type("java.io.FileWriter");
+var LocalDateTime = Java.type("java.time.LocalDateTime");
+var InputStreamReader = Java.type("java.io.InputStreamReader");
+var PrintWriter = Java.type("java.io.PrintWriter");
+var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
+var System = Java.type("java.lang.System");
+
+// read multiple lines of input from stdin till user
+// enters an empty line
+function input(endMarker, prompt) {
+ if (!endMarker) {
+ endMarker = "";
+ }
+
+ if (!prompt) {
+ prompt = " >> ";
+ }
+
+ var str = "";
+ var reader = new BufferedReader(new InputStreamReader(System.in));
+ var line;
+ while (true) {
+ System.out.print(prompt);
+ line = reader.readLine();
+ if (line == null || line == endMarker) {
+ break;
+ }
+ str += line + "\n";
+ }
+ return str;
+}
+
+// write the string to the given file
+function writeTo(file, str) {
+ var w = new PrintWriter(new FileWriter(file));
+ try {
+ w.print(str);
+ } finally {
+ w.close();
+ }
+}
+
+// generate Java code with user's input
+// put inside generated main method
+function generate(className) {
+ var usercode = input();
+ if (usercode == "") {
+ return false;
+ }
+
+ var fullcode = <<EOF
+// userful imports, add more here if you want
+// more imports.
+import static java.lang.System.*;
+import java.io.*;
+import java.net.*;
+import java.math.*;
+import java.nio.file.*;
+import java.time.*;
+import java.time.chrono.*;
+import java.time.format.*;
+import java.time.temporal.*;
+import java.time.zone.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+
+public class ${className} {
+ public static void main(String[] args) throws Exception {
+ ${usercode}
+ }
+}
+EOF
+
+ writeTo("${className}.java", fullcode);
+ return true;
+}
+
+// execute code command
+function exec(args) {
+ // build child process and start it!
+ new ProcessBuilder(Arrays.asList(args.split(' ')))
+ .inheritIO()
+ .start()
+ .waitFor();
+}
+
+// generate unique name
+function uniqueName() {
+ var now = LocalDateTime.now().toString();
+ // replace unsafe chars with '_'
+ return "JavaShell" + now.replace(/-|:|\./g, '_');
+}
+
+// read-compile-run loop
+while(true) {
+ var className = uniqueName();
+ if (generate(className)) {
+ exec("javac ${className}.java");
+ exec("java ${className}");
+ } else {
+ break;
+ }
+}
diff --git a/samples/jsadapter_dom.js b/samples/jsadapter_dom.js
new file mode 100644
index 00000000..e86c6d2f
--- /dev/null
+++ b/samples/jsadapter_dom.js
@@ -0,0 +1,189 @@
+#// Usage: jjs -scripting jsadapter_dom.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple example that demonstrates reading XML Rss feed
+// to generate a HTML file from script and show it by browser
+// Uses XML DOM parser and DOM element wrapped by script
+// "proxy" (JSAdapter constructor)
+
+// Java classes used
+var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory");
+var Node = Java.type("org.w3c.dom.Node");
+var File = Java.type("java.io.File");
+var FileWriter = Java.type("java.io.FileWriter");
+var PrintWriter = Java.type("java.io.PrintWriter");
+
+// constants from Node class
+var ELEMENT_NODE = Node.ELEMENT_NODE;
+var TEXT_NODE = Node.TEXT_NODE;
+
+// parse XML from uri and return Document
+function parseXML(uri) {
+ var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder();
+ return docBuilder["parse(java.lang.String)"](uri);
+}
+
+// get child Elements of given name of the parent element given
+function getChildElements(elem, name) {
+ var nodeList = elem.childNodes;
+ var childElems = [];
+ var len = nodeList.length;
+ for (var i = 0; i < len; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType == ELEMENT_NODE &&
+ node.tagName == name) {
+ childElems.push(wrapElement(node));
+ }
+ }
+
+ return childElems;
+}
+
+// get concatenated child text content of an Element
+function getElemText(elem) {
+ var nodeList = elem.childNodes;
+ var len = nodeList.length;
+ var text = '';
+ for (var i = 0; i < len; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType == TEXT_NODE) {
+ text += node.nodeValue;
+ }
+ }
+
+ return text;
+}
+
+// Wrap DOM Element object as a convenient script object
+// using JSAdapter. JSAdapter is like java.lang.reflect.Proxy
+// in that it allows property access, method calls be trapped
+// by 'magic' methods like __get__, __call__.
+function wrapElement(elem) {
+ if (! elem) {
+ return elem;
+ }
+ return new JSAdapter() {
+ // getter to expose child elements and attributes by name
+ __get__: function(name) {
+ if (typeof name == 'string') {
+ if (name.startsWith('@')) {
+ var attr = elem.getAttributeNode(name.substring(1));
+ return !attr? undefined : attr.value;
+ }
+
+ var arr = getChildElements(elem, name);
+ if (arr.length == 1) {
+ // single child element, expose as single element
+ return arr[0];
+ } else {
+ // multiple children of given name, expose as array
+ return arr;
+ }
+ }
+ return undefined;
+ },
+
+ __call__: function(name) {
+ // toString override to get text content of this Element
+ if (name == 'toString' || name == 'valueOf') {
+ return getElemText(elem);
+ }
+ return undefined;
+ }
+ }
+}
+
+// generate HTML using here-doc and string interpolation
+function getBooksHtml() {
+ var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss");
+ // wrap document root Element as script convenient object
+ var rss = wrapElement(doc.documentElement);
+ print("rss file version " + rss['@version']);
+
+ var str = <<HEAD
+
+<html>
+<title>${rss.channel.title}</title>
+<body>
+<h1>${rss.channel.description}</h1>
+<p>
+Published on ${rss.channel.pubDate}
+</p>
+
+HEAD
+
+ var items = rss.channel.item;
+ for each (var i in items) {
+ str += <<LIST
+
+<dl>
+<dt><a href="${i.link}">${i.title}</a></dt>
+<dd>${i.description}</dd>
+</dl>
+
+LIST
+ }
+ str += <<END
+
+</body>
+</html>
+
+END
+ return str;
+}
+
+// write the string to the given file
+function writeTo(file, str) {
+ var w = new PrintWriter(new FileWriter(file));
+ try {
+ w.print(str);
+ } finally {
+ w.close();
+ }
+}
+
+// generate books HTML
+var str = getBooksHtml();
+
+// write to file. __DIR__ is directory where
+// this script is stored.
+var file = new File(__DIR__ + "books.html");
+writeTo(file, str);
+
+// show it by desktop browser
+try {
+ var Desktop = Java.type("java.awt.Desktop");
+ Desktop.desktop.browse(file.toURI());
+} catch (e) {
+ print(e);
+}
diff --git a/samples/jsobject.js b/samples/jsobject.js
new file mode 100644
index 00000000..48434d7d
--- /dev/null
+++ b/samples/jsobject.js
@@ -0,0 +1,75 @@
+#// Usage: jjs -scripting -cp . jsobject.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// This sample demonstrats how to expose a
+// script friendly object from your java code
+// by implementing jdk.nashorn.api.scripting.JSObject
+
+// compile the java program
+`javac BufferArray.java`;
+
+// print error, if any and exit
+if ($ERR != '') {
+ print($ERR);
+ exit($EXIT);
+}
+
+// create BufferArray
+var BufferArray = Java.type("BufferArray");
+var bb = new BufferArray(10);
+
+// 'magic' methods called to retrieve set/get
+// properties on BufferArray instance
+var len = bb.length;
+print("bb.length = " + len)
+for (var i = 0; i < len; i++) {
+ bb[i] = i*i;
+}
+
+for (var i = 0; i < len; i++) {
+ print(bb[i]);
+}
+
+// get underlying buffer by calling a method
+// on BufferArray magic object
+
+// 'buf' is a function member
+print(typeof bb.buf);
+var buf = bb.buf();
+
+// use retrieved underlying nio buffer
+var cap = buf.capacity();
+print("buf.capacity() = " + cap);
+for (var i = 0; i < cap; i++) {
+ print(buf.get(i));
+}
diff --git a/samples/jsobject_mapreduce.js b/samples/jsobject_mapreduce.js
new file mode 100644
index 00000000..ff34940b
--- /dev/null
+++ b/samples/jsobject_mapreduce.js
@@ -0,0 +1,62 @@
+#// Usage: jjs -scripting -cp . jsobject_mapreduce.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Many Array.prototype functions such as map,
+// filter, reduce, reduceRight, every, some are generic.
+// These functions accept ECMAScript array as well as
+// many array-like objects including JSObjects.
+// See also http://en.wikipedia.org/wiki/MapReduce
+
+`javac BufferArray.java`;
+
+var BufferArray = Java.type("BufferArray");
+var buf = new BufferArray(10);
+
+var map = Array.prototype.map;
+var filter = Array.prototype.filter;
+var reduce = Array.prototype.reduce;
+
+// make random list of numbers
+for (var i = 0; i < 10; i++)
+ buf[i] = Math.random();
+
+var forEach = Array.prototype.forEach;
+// print numbers in the list
+forEach.call(buf, function(x) print(x));
+
+// print sum of squares of the random numbers
+print("Square sum:",
+ reduce.call(
+ map.call(buf, function(x) x*x),
+ function(x, y) x + y)
+);
diff --git a/samples/jsonviewer.js b/samples/jsonviewer.js
new file mode 100644
index 00000000..804fef50
--- /dev/null
+++ b/samples/jsonviewer.js
@@ -0,0 +1,120 @@
+#// Usage: jjs -fx jsonviewer.js
+// or
+// jjs -fx jsonviewer.js -- <url-of-json-doc>
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+if (! $OPTIONS._fx) {
+ print("Usage: jjs -fx jsonviewer.js -- <url-of-json-doc>");
+ exit(1);
+}
+
+// This example downloads a JSON file from a URL and
+// shows the same as a JavaFX tree view.
+
+// Using JavaFX from Nashorn. See also:
+// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html
+
+// JavaFX classes used
+var StackPane = Java.type("javafx.scene.layout.StackPane");
+var Scene = Java.type("javafx.scene.Scene");
+var TreeItem = Java.type("javafx.scene.control.TreeItem");
+var TreeView = Java.type("javafx.scene.control.TreeView");
+
+// read text content of a URL
+function readTextFromURL(url) {
+ // equivalent to
+ //
+ // import java.io.*;
+ // import java.net.*;
+ // import java.lang.StringBuffer;
+ //
+ // only inside the 'with' statement
+ with (new JavaImporter(java.io,
+ java.net,
+ java.lang.StringBuilder)) {
+ var buf = new StringBuilder();
+ var u = new URL(url);
+ var reader = new BufferedReader(
+ new InputStreamReader(u.openStream()));
+ var line = null;
+ try {
+ while ((line = reader.readLine()) != null)
+ buf.append(line).append('\n');
+ } finally {
+ reader.close();
+ }
+
+ return buf.toString();
+ }
+}
+
+// Create a javafx TreeItem to view a script object
+function treeItemForObject(obj, name) {
+ var item = new TreeItem(name);
+ for (var prop in obj) {
+ var node = obj[prop];
+ if (typeof node == 'object') {
+ if (node == null) {
+ // skip nulls
+ continue;
+ }
+
+ if (Array.isArray(node) && node.length == 0) {
+ // skip empty arrays
+ continue;
+ }
+
+ var subitem = treeItemForObject(node, prop);
+ } else {
+ var subitem = new TreeItem(prop + ": " + node);
+ }
+ item.children.add(subitem);
+ }
+ return item;
+}
+
+var DEFAULT_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&amp;mode=json&amp;units=metric&amp;cnt=7`";
+
+var url = arguments.length == 0? DEFAULT_URL : arguments[0];
+var obj = JSON.parse(readTextFromURL(url));
+
+// JavaFX start method
+function start(stage) {
+ stage.title = "JSON Viewer";
+ var rootItem = treeItemForObject(obj, url);
+ var tree = new TreeView(rootItem);
+ var root = new StackPane();
+ root.children.add(tree);
+ stage.scene = new Scene(root, 300, 450);
+ stage.show();
+}
diff --git a/samples/letter.js b/samples/letter.js
index cbee92d0..304bf1fb 100644
--- a/samples/letter.js
+++ b/samples/letter.js
@@ -1,3 +1,5 @@
+#// Usage: jjs -scripting letter.js -- <sender> <recipient>
+
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
*
diff --git a/samples/list_mapreduce.js b/samples/list_mapreduce.js
new file mode 100644
index 00000000..033f4d76
--- /dev/null
+++ b/samples/list_mapreduce.js
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Usage: jjs list_mapreduce.js
+
+// Many Array.prototype functions such as map,
+// filter, reduce, reduceRight, every, some are generic.
+// These functions accept ECMAScript array as well as
+// many array-like objects including java.util.ArrayLists.
+// So, you can do map/filter/reduce with Java streams or
+// you can also use Array.prototype functions as below.
+// See also http://en.wikipedia.org/wiki/MapReduce
+
+var ArrayList = Java.type("java.util.ArrayList");
+var list = new ArrayList();
+list.add("nashorn");
+list.add("ecmascript");
+list.add("javascript");
+list.add("js");
+list.add("scheme");
+
+var map = Array.prototype.map;
+var filter = Array.prototype.filter;
+var reduce = Array.prototype.reduce;
+
+// sum of word lengths
+print("Sum word length:",
+ reduce.call(
+ map.call(list, function(x) x.length),
+ function(x, y) x + y)
+);
+
+// filter use to filter out "j*" and concatenate rest with ":"
+// after uppercasing all strings
+print(
+ reduce.call(
+ map.call(
+ filter.call(list, function(x) !x.startsWith("j")),
+ function(x) x.toUpperCase()),
+ function(x, y) x + ":" + y)
+);
+
+// another list example involving numbers
+list.clear();
+// make random list of numbers
+for (var i = 0; i < 10; i++)
+ list.add(Math.random());
+
+var forEach = Array.prototype.forEach;
+// print numbers in the list
+forEach.call(list, function(x) print(x));
+
+// print sum of squares of the random numbers
+print("Square sum:",
+ reduce.call(
+ map.call(list, function(x) x*x),
+ function(x, y) x + y)
+);
diff --git a/samples/locales.js b/samples/locales.js
new file mode 100644
index 00000000..ae42f969
--- /dev/null
+++ b/samples/locales.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple program that lists available locals. This is ECMAScript
+// port of Java example by @brunoborges
+
+// Java classes used
+var Arrays = Java.type("java.util.Arrays");
+var Collectors = Java.type("java.util.stream.Collectors");
+var JString = Java.type("java.lang.String");
+var Locale = Java.type("java.util.Locale");
+
+var formatStr = "Country : %s \t\t\t\t:\t Country Code : %s";
+
+// Nashorn allows script functions to be passed
+// whereever Java8 lambdas are expected.
+
+// Nashorn also supports "expression closures" supported by
+// Mozilla JavaScript 1.8 version. See also
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8
+
+// The following prints locales in (country) display name order
+var list = Arrays.asList(Locale.getISOCountries())
+ .stream()
+ .map(function(x) new Locale("", x))
+ .sorted(function(c0, c1) c0.displayCountry.compareTo(c1.displayCountry))
+ .map(function(l) JString.format(formatStr, l.displayCountry, l.country))
+ .collect(Collectors.toList());
+
+list.forEach(print);
diff --git a/samples/logisticmap.js b/samples/logisticmap.js
new file mode 100644
index 00000000..74198475
--- /dev/null
+++ b/samples/logisticmap.js
@@ -0,0 +1,82 @@
+#// Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R>
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Logistic map viewer using Java8 Streams and JavaFX
+// See also http://en.wikipedia.org/wiki/Logistic_map
+
+if (!$OPTIONS._fx || arguments.length < 2) {
+ print("Usage: jjs -fx -scripting logisticmap.js -- <initial_x> <R>");
+ exit(1);
+}
+
+// parameters for the logistic map
+var x = parseFloat(arguments[0]);
+var R = parseFloat(arguments[1]);
+var NUM_POINTS = arguments.length > 2? parseFloat(arguments[2]) : 20;
+
+// Java classes used
+var DoubleStream = Java.type('java.util.stream.DoubleStream');
+var LineChart = Java.type("javafx.scene.chart.LineChart");
+var NumberAxis = Java.type("javafx.scene.chart.NumberAxis");
+var Scene = Java.type("javafx.scene.Scene");
+var Stage = Java.type("javafx.stage.Stage");
+var XYChart = Java.type("javafx.scene.chart.XYChart");
+
+function start(stage) {
+ stage.title = "Logistic Map: initial x = ${x}, R = ${R}";
+ // make chart
+ var xAxis = new NumberAxis();
+ var yAxis = new NumberAxis();
+ var lineChart = new LineChart(xAxis, yAxis);
+ xAxis.setLabel("iteration");
+ yAxis.setLabel("x");
+ // make chart data series
+ var series = new XYChart.Series();
+ var data = series.data;
+ // populate data using logistic iteration
+ var i = 0;
+ DoubleStream
+ .generate(function() x = R*x*(1-x))
+ .limit(NUM_POINTS)
+ .forEach(
+ function(value) {
+ data.add(new XYChart.Data(i, value));
+ i++;
+ }
+ );
+ // add to stage
+ var scene = new Scene(lineChart, 800, 600);
+ lineChart.data.add(series);
+ stage.scene = scene;
+ stage.show();
+}
diff --git a/samples/options.js b/samples/options.js
new file mode 100644
index 00000000..3a10346c
--- /dev/null
+++ b/samples/options.js
@@ -0,0 +1,37 @@
+#// Usage: jjs -scripting options.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// print all option names and values
+for (i in $OPTIONS) {
+ print(i, '=', $OPTIONS[i]);
+}
diff --git a/samples/readLine.js b/samples/readLine.js
new file mode 100644
index 00000000..9807d3b5
--- /dev/null
+++ b/samples/readLine.js
@@ -0,0 +1,38 @@
+#// Usage: jjs -scripting greeting.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// readLine prints prompt and reads user response
+var name = readLine("Your name please: ");
+
+// user name is interpolated within string
+print("Hello ${name}");
diff --git a/samples/sam_function.js b/samples/sam_function.js
new file mode 100644
index 00000000..84064732
--- /dev/null
+++ b/samples/sam_function.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports passing script functions whenever
+// a SAM (single abstract method) type object is expected
+
+var System = Java.type("java.lang.System");
+var Timer = Java.type("java.util.Timer");
+var timer = new Timer();
+
+// schedule method accepts java.util.TimerTask
+// which is a single-abstract-method type. you
+// can pass a script function and nashorn will
+// wrap it as SAM implementor.
+
+timer.schedule(function() {
+ print("Hello World!");
+}, 1000);
+
+// wait for timer thread to print by
+// reading from stdin.
+print("press any key to exit after message from timer...");
+System.in.read();
diff --git a/samples/shell.js b/samples/shell.js
index fc4ce9aa..93965387 100644
--- a/samples/shell.js
+++ b/samples/shell.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,50 +29,53 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/**
- * This is a simple shell tool in JavaScript.
+// Usage: jjs shell.js
+
+/* This is a simple shell tool in JavaScript.
*
* Runs any operating system command using Java "exec". When "eval" command is
* used, evaluates argument(s) as JavaScript code.
*/
-var imports = new JavaImporter(java.io, java.lang, java.util);
+(function() {
+ // Java classes used
+ var Arrays = Java.type("java.util.Arrays");
+ var BufferedReader = Java.type("java.io.BufferedReader");
+ var InputStreamReader = Java.type("java.io.InputStreamReader");
+ var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
+ var System = Java.type("java.lang.System");
-function prompt() {
- java.lang.System.out.print(">");
-}
+ // print prompt
+ function prompt() {
+ System.out.print("> ");
+ }
-with (imports) {
- var reader = new BufferedReader(new InputStreamReader(System["in"]));
- var line = null;
+ var reader = new BufferedReader(new InputStreamReader(System.in));
prompt();
- while ((line = reader.readLine()) != null) {
- if (line != "") {
- var args = line.split(" ");
+ // read and evaluate each line from stdin
+ reader.lines().forEach(function(line) {
+ if (! line.isEmpty()) {
+ var args = line.split(' ');
try {
- if (args[0] == "eval") {
- var code = line.substring("eval".length);
+ // special 'eval' command to evaluate JS code
+ if (args[0] == 'eval') {
+ var code = line.substring('eval'.length);
var res = eval(code);
if (res != undefined) {
print(res);
}
} else {
- var argList = new ArrayList();
- for (i in args) { argList.add(args[i]); }
- var procBuilder = new ProcessBuilder(argList);
- procBuilder.redirectErrorStream();
- var proc = procBuilder.start();
- var out = new BufferedReader(new InputStreamReader(proc.getInputStream()));
- var line = null;
- while ((line = out.readLine()) != null) {
- System.out.println(line);
- }
- proc.waitFor();
+ // build child process and start it!
+ new ProcessBuilder(Arrays.asList(args))
+ .inheritIO()
+ .start()
+ .waitFor();
}
} catch (e) {
+ // print exception, if any
print(e);
}
}
prompt();
- }
-}
+ })
+})()
diff --git a/samples/stack.js b/samples/stack.js
new file mode 100644
index 00000000..295ad20f
--- /dev/null
+++ b/samples/stack.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// nashorn supports 'stack' property on ECMAScript
+// error objects. This property's value is a string
+// that shows script stack trace.
+
+function g() {
+ throw new Error("wrong");
+}
+
+function f() {
+ g();
+}
+
+// Output looks something like:
+//
+// Error: wrong
+// at g (stack.js:37)
+// at f (stack.js:41)
+// at <program> (stack.js:52)
+
+try {
+ f();
+} catch (e) {
+ print(e.stack);
+}
diff --git a/samples/test.js b/samples/test.js
index ecdaf846..1a7e8061 100644
--- a/samples/test.js
+++ b/samples/test.js
@@ -30,4 +30,3 @@
*/
print("Hello World");
-
diff --git a/samples/uniform_random.js b/samples/uniform_random.js
new file mode 100644
index 00000000..a82cd0bb
--- /dev/null
+++ b/samples/uniform_random.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// generate/print 100 uniformly distributed random values
+// and print summary statistics on it
+
+var DoubleStream = Java.type("java.util.stream.DoubleStream");
+
+// pass script function when a lambda is required
+// Math.random passed here for double generator lambda
+// print passed to forEach method
+
+DoubleStream
+ .generate(Math.random)
+ .limit(100)
+ .forEach(print);
+
+print(DoubleStream
+ .generate(Math.random)
+ .limit(100)
+ .summaryStatistics());
diff --git a/samples/uniq.js b/samples/uniq.js
index 3da8480b..cbd2c34d 100644
--- a/samples/uniq.js
+++ b/samples/uniq.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,27 +29,28 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/**
- * Prints unique lines from a given file.
- */
+// Usage: jjs uniq.js
+// or: jjs uniq.js -- <file>
-if (arguments.length != 1) {
- print("Usage: jjs uniq.js -- <file>");
- java.lang.System.exit(1);
-}
+// omit repeated lines and print unique lines
-var imports = new JavaImporter(java.io);
+var BufferedReader = Java.type("java.io.BufferedReader");
+var FileReader = Java.type("java.io.FileReader");
+var InputStreamReader = Java.type("java.io.InputStreamReader");
+var System = Java.type("java.lang.System");
+// use object as set - but insertion order preserved
var uniqueLines = {};
-with (imports) {
- var reader = new BufferedReader(new FileReader(arguments[0]));
- while ((line = reader.readLine()) != null) {
- // using a JS object as a map...
- uniqueLines[line] = true;
- }
-}
+var reader = arguments.length > 0 ?
+ new FileReader(arguments[0]) :
+ new InputStreamReader(System.in);
+reader = new BufferedReader(reader);
+
+// add unique lines
+reader.lines().forEach(function(line) {
+ uniqueLines[line] = true;
+})
-// now print the collected lines
-for (i in uniqueLines) {
- print(i);
+for (line in uniqueLines) {
+ print(line);
}
diff --git a/samples/uniqs.js b/samples/uniqs.js
new file mode 100644
index 00000000..57eb7c52
--- /dev/null
+++ b/samples/uniqs.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Usage: jjs uniqs.js -- <file>
+// omit repeated lines and print unique lines
+// But this version uses Stream API
+
+if (arguments.length < 1) {
+ print("Usage: jjs uniqs.js -- <file>");
+ exit(1);
+}
+
+var Files = Java.type("java.nio.file.Files");
+var FileSystems = Java.type("java.nio.file.FileSystems");
+print('Unique lines:',
+ Files
+ .lines(FileSystems.default.getPath(arguments[0]))
+ .distinct()
+ .peek(print)
+ .count());
diff --git a/samples/weather.js b/samples/weather.js
new file mode 100644
index 00000000..75c6b265
--- /dev/null
+++ b/samples/weather.js
@@ -0,0 +1,63 @@
+#// usage: jjs -scripting weather.js
+
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// Simple nashorn example showing back-quote exec process,
+// JSON and Java8 streams
+
+var Arrays = Java.type("java.util.Arrays");
+
+// use curl to download JSON weather data from the net
+// use backquote -scripting mode syntax to exec a process
+
+`curl http://api.openweathermap.org/data/2.5/forecast/daily?q=Chennai&amp;mode=json&amp;units=metric&amp;cnt=7`;
+
+// parse JSON
+var weather = JSON.parse($OUT);
+
+// pull out humidity as array
+var humidity = weather.list.map(function(curVal) {
+ return curVal.humidity;
+})
+
+// Stream API to print stat
+print("Humidity");
+print(Arrays["stream(int[])"](humidity).summaryStatistics());
+
+// pull maximum day time temperature
+var temp = weather.list.map(function(curVal) {
+ return curVal.temp.max;
+});
+
+// Stream API to print stat
+print("Max Temperature");
+print(Arrays["stream(double[])"](temp).summaryStatistics());
diff --git a/src/jdk/internal/dynalink/beans/BeanLinker.java b/src/jdk/internal/dynalink/beans/BeanLinker.java
index 519036b3..d0ad96ba 100644
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java
+++ b/src/jdk/internal/dynalink/beans/BeanLinker.java
@@ -113,6 +113,8 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
// explicit property is beneficial for them.
// REVISIT: is it maybe a code smell that "dyn:getLength" is not needed?
setPropertyGetter("length", GET_ARRAY_LENGTH, ValidationType.IS_ARRAY);
+ } else if(List.class.isAssignableFrom(clazz)) {
+ setPropertyGetter("length", GET_COLLECTION_LENGTH, ValidationType.INSTANCE_OF);
}
}
diff --git a/src/jdk/nashorn/api/scripting/NashornException.java b/src/jdk/nashorn/api/scripting/NashornException.java
index d5ec5bb4..a5f8c24a 100644
--- a/src/jdk/nashorn/api/scripting/NashornException.java
+++ b/src/jdk/nashorn/api/scripting/NashornException.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.List;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ScriptObject;
/**
* This is base exception for all Nashorn exceptions. These originate from
@@ -44,11 +45,13 @@ import jdk.nashorn.internal.runtime.ECMAErrors;
@SuppressWarnings("serial")
public abstract class NashornException extends RuntimeException {
// script file name
- private final String fileName;
+ private String fileName;
// script line number
- private final int line;
+ private int line;
// script column number
- private final int column;
+ private int column;
+ // underlying ECMA error object - lazily initialized
+ private Object ecmaError;
/** script source name used for "engine.js" */
public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
@@ -122,6 +125,15 @@ public abstract class NashornException extends RuntimeException {
}
/**
+ * Set the source file name for this {@code NashornException}
+ *
+ * @param fileName the file name
+ */
+ public final void setFileName(final String fileName) {
+ this.fileName = fileName;
+ }
+
+ /**
* Get the line number for this {@code NashornException}
*
* @return the line number
@@ -131,15 +143,33 @@ public abstract class NashornException extends RuntimeException {
}
/**
+ * Set the line number for this {@code NashornException}
+ *
+ * @param line the line number
+ */
+ public final void setLineNumber(final int line) {
+ this.line = line;
+ }
+
+ /**
* Get the column for this {@code NashornException}
*
- * @return the column
+ * @return the column number
*/
public final int getColumnNumber() {
return column;
}
/**
+ * Set the column for this {@code NashornException}
+ *
+ * @param column the column number
+ */
+ public final void setColumnNumber(final int column) {
+ this.column = column;
+ }
+
+ /**
* Returns array javascript stack frames from the given exception object.
*
* @param exception exception from which stack frames are retrieved and filtered
@@ -155,6 +185,11 @@ public abstract class NashornException extends RuntimeException {
if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
methodName = "<program>";
}
+
+ if (methodName.contains(CompilerConstants.ANON_FUNCTION_PREFIX.symbolName())) {
+ methodName = "<anonymous>";
+ }
+
filtered.add(new StackTraceElement(className, methodName,
st.getFileName(), st.getLineNumber()));
}
@@ -188,4 +223,43 @@ public abstract class NashornException extends RuntimeException {
}
return buf.toString();
}
+
+ protected Object getThrown() {
+ return null;
+ }
+
+ protected NashornException initEcmaError(final ScriptObject global) {
+ if (ecmaError != null) {
+ return this; // initialized already!
+ }
+
+ final Object thrown = getThrown();
+ if (thrown instanceof ScriptObject) {
+ setEcmaError(ScriptObjectMirror.wrap(thrown, global));
+ } else {
+ setEcmaError(thrown);
+ }
+
+ return this;
+ }
+
+ /**
+ * Return the underlying ECMA error object, if available.
+ *
+ * @return underlying ECMA Error object's mirror or whatever was thrown
+ * from script such as a String, Number or a Boolean.
+ */
+ public Object getEcmaError() {
+ return ecmaError;
+ }
+
+ /**
+ * Return the underlying ECMA error object, if available.
+ *
+ * @param ecmaError underlying ECMA Error object's mirror or whatever was thrown
+ * from script such as a String, Number or a Boolean.
+ */
+ public void setEcmaError(final Object ecmaError) {
+ this.ecmaError = ecmaError;
+ }
}
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 83b0bee8..7ebe5c91 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -27,16 +27,14 @@ package jdk.nashorn.api.scripting;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
-import java.nio.charset.Charset;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
@@ -57,9 +55,9 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -99,7 +97,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
private final boolean _global_per_engine;
// This is the initial default Nashorn global object.
// This is used as "shared" global if above option is true.
- private final ScriptObject global;
+ private final Global global;
// initialized bit late to be made 'final'.
// Property object for "context" property of global object.
private volatile Property contextProperty;
@@ -124,21 +122,21 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
- // load engine.js and return content as a char[]
+ // load engine.js
@SuppressWarnings("resource")
- private static char[] loadEngineJSSource() {
+ private static Source loadEngineJSSource() {
final String script = "resources/engine.js";
try {
- final InputStream is = AccessController.doPrivileged(
- new PrivilegedExceptionAction<InputStream>() {
+ return AccessController.doPrivileged(
+ new PrivilegedExceptionAction<Source>() {
@Override
- public InputStream run() throws Exception {
+ public Source run() throws IOException {
final URL url = NashornScriptEngine.class.getResource(script);
- return url.openStream();
+ return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
}
- });
- return Source.readFully(new InputStreamReader(is));
- } catch (final PrivilegedActionException | IOException e) {
+ }
+ );
+ } catch (final PrivilegedActionException e) {
if (Context.DEBUG) {
e.printStackTrace();
}
@@ -147,7 +145,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
// Source object for engine.js
- private static final Source ENGINE_SCRIPT_SRC = new Source(NashornException.ENGINE_SCRIPT_SOURCE_NAME, loadEngineJSSource());
+ private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
this(factory, DEFAULT_OPTIONS, appLoader);
@@ -264,7 +262,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
if (ctxt != null) {
final int scope = ctxt.getAttributesScope(name);
- final ScriptObject ctxtGlobal = getNashornGlobalFrom(ctxt);
+ final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
if (scope != -1) {
return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
}
@@ -282,19 +280,14 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
try {
- if (reader instanceof URLReader) {
- final URL url = ((URLReader)reader).getURL();
- final Charset cs = ((URLReader)reader).getCharset();
- return new Source(url.toString(), url, cs);
- }
- return new Source(getScriptName(ctxt), Source.readFully(reader));
- } catch (final IOException e) {
+ return sourceFor(getScriptName(ctxt), reader);
+ } catch (IOException e) {
throw new ScriptException(e);
}
}
private static Source makeSource(final String src, final ScriptContext ctxt) {
- return new Source(getScriptName(ctxt), src);
+ return sourceFor(getScriptName(ctxt), src);
}
private static String getScriptName(final ScriptContext ctxt) {
@@ -317,7 +310,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
ScriptObject realSelf = null;
- ScriptObject realGlobal = null;
+ Global realGlobal = null;
if(thiz == null) {
// making interface out of global functions
realSelf = realGlobal = getNashornGlobalFrom(context);
@@ -346,7 +339,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
try {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != realGlobal);
try {
if (globalChanged) {
@@ -371,7 +364,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
// Retrieve nashorn Global object for a given ScriptContext object
- private ScriptObject getNashornGlobalFrom(final ScriptContext ctxt) {
+ private Global getNashornGlobalFrom(final ScriptContext ctxt) {
if (_global_per_engine) {
// shared single global object for all ENGINE_SCOPE Bindings
return global;
@@ -380,18 +373,18 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
final Bindings bindings = ctxt.getBindings(ScriptContext.ENGINE_SCOPE);
// is this Nashorn's own Bindings implementation?
if (bindings instanceof ScriptObjectMirror) {
- final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)bindings);
- if (sobj != null) {
- return sobj;
+ final Global glob = globalFromMirror((ScriptObjectMirror)bindings);
+ if (glob != null) {
+ return glob;
}
}
// Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
Object scope = bindings.get(NASHORN_GLOBAL);
if (scope instanceof ScriptObjectMirror) {
- final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
- if (sobj != null) {
- return sobj;
+ final Global glob = globalFromMirror((ScriptObjectMirror)scope);
+ if (glob != null) {
+ return glob;
}
}
@@ -399,14 +392,14 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
// Create new global instance mirror and associate with the Bindings.
final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
bindings.put(NASHORN_GLOBAL, mirror);
- return mirror.getScriptObject();
+ return mirror.getHomeGlobal();
}
// Retrieve nashorn Global object from a given ScriptObjectMirror
- private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
+ private Global globalFromMirror(final ScriptObjectMirror mirror) {
ScriptObject sobj = mirror.getScriptObject();
- if (sobj instanceof GlobalObject && isOfContext(sobj, nashornContext)) {
- return sobj;
+ if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) {
+ return (Global)sobj;
}
return null;
@@ -414,15 +407,15 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
// Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
- final ScriptObject newGlobal = createNashornGlobal(ctxt);
+ final Global newGlobal = createNashornGlobal(ctxt);
return new ScriptObjectMirror(newGlobal, newGlobal);
}
// Create a new Nashorn Global object
- private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
- final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
+ private Global createNashornGlobal(final ScriptContext ctxt) {
+ final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
@Override
- public ScriptObject run() {
+ public Global run() {
try {
return nashornContext.newGlobal();
} catch (final RuntimeException e) {
@@ -460,7 +453,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
// scripts should see "context" and "engine" as variables in the given global object
- private void setContextVariables(final ScriptObject ctxtGlobal, final ScriptContext ctxt) {
+ private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
// set "context" global variable via contextProperty - because this
// property is non-writable
contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
@@ -470,7 +463,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
// if no arguments passed, expose it
if (! (args instanceof ScriptObject)) {
- args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
+ args = ctxtGlobal.wrapAsObject(args);
ctxtGlobal.set("arguments", args, false);
}
}
@@ -478,16 +471,19 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
name.getClass(); // null check
+ Global invokeGlobal = null;
ScriptObjectMirror selfMirror = null;
if (selfObject instanceof ScriptObjectMirror) {
selfMirror = (ScriptObjectMirror)selfObject;
if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
}
+ invokeGlobal = selfMirror.getHomeGlobal();
} else if (selfObject instanceof ScriptObject) {
// invokeMethod called from script code - in which case we may get 'naked' ScriptObject
// Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
+ invokeGlobal = oldGlobal;
if (oldGlobal == null) {
throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
}
@@ -499,7 +495,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
} else if (selfObject == null) {
// selfObject is null => global function call
- final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
+ final Global ctxtGlobal = getNashornGlobalFrom(context);
+ invokeGlobal = ctxtGlobal;
selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
}
@@ -511,7 +508,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
if (cause instanceof NoSuchMethodException) {
throw (NoSuchMethodException)cause;
}
- throwAsScriptException(e);
+ throwAsScriptException(e, invokeGlobal);
throw new AssertionError("should not reach here");
}
}
@@ -528,11 +525,36 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
}
- private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final ScriptObject ctxtGlobal) throws ScriptException {
+ private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+ final Global oldGlobal = Context.getGlobal();
+ final boolean globalChanged = (oldGlobal != ctxtGlobal);
+ try {
+ if (globalChanged) {
+ Context.setGlobal(ctxtGlobal);
+ }
+
+ final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
+
+ // set ScriptContext variables if ctxt is non-null
+ if (ctxt != null) {
+ setContextVariables(ctxtGlobal, ctxt);
+ }
+ return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+ } catch (final Exception e) {
+ throwAsScriptException(e, ctxtGlobal);
+ throw new AssertionError("should not reach here");
+ } finally {
+ if (globalChanged) {
+ Context.setGlobal(oldGlobal);
+ }
+ }
+ }
+
+ private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
}
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
if (globalChanged) {
@@ -545,7 +567,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
} catch (final Exception e) {
- throwAsScriptException(e);
+ throwAsScriptException(e, ctxtGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
@@ -554,7 +576,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
}
- private static void throwAsScriptException(final Exception e) throws ScriptException {
+ private static void throwAsScriptException(final Exception e, final Global global) throws ScriptException {
if (e instanceof ScriptException) {
throw (ScriptException)e;
} else if (e instanceof NashornException) {
@@ -562,6 +584,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
final ScriptException se = new ScriptException(
ne.getMessage(), ne.getFileName(),
ne.getLineNumber(), ne.getColumnNumber());
+ ne.initEcmaError(global);
se.initCause(e);
throw se;
} else if (e instanceof RuntimeException) {
@@ -573,18 +596,38 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
}
private CompiledScript asCompiledScript(final Source source) throws ScriptException {
- final ScriptFunction func = compileImpl(source, context);
+ final Context.MultiGlobalCompiledScript mgcs;
+ final ScriptFunction func;
+ final Global oldGlobal = Context.getGlobal();
+ final Global newGlobal = getNashornGlobalFrom(context);
+ final boolean globalChanged = (oldGlobal != newGlobal);
+ try {
+ if (globalChanged) {
+ Context.setGlobal(newGlobal);
+ }
+
+ mgcs = nashornContext.compileScript(source);
+ func = mgcs.getFunction(newGlobal);
+ } catch (final Exception e) {
+ throwAsScriptException(e, newGlobal);
+ throw new AssertionError("should not reach here");
+ } finally {
+ if (globalChanged) {
+ Context.setGlobal(oldGlobal);
+ }
+ }
+
return new CompiledScript() {
@Override
public Object eval(final ScriptContext ctxt) throws ScriptException {
- final ScriptObject globalObject = getNashornGlobalFrom(ctxt);
- // Are we running the script in the correct global?
+ final Global globalObject = getNashornGlobalFrom(ctxt);
+ // Are we running the script in the same global in which it was compiled?
if (func.getScope() == globalObject) {
return evalImpl(func, ctxt, globalObject);
}
- // ScriptContext with a different global. Compile again!
- // Note that we may still hit per-global compilation cache.
- return evalImpl(compileImpl(source, ctxt), ctxt, globalObject);
+
+ // different global
+ return evalImpl(mgcs, ctxt, globalObject);
}
@Override
public ScriptEngine getEngine() {
@@ -597,8 +640,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return compileImpl(source, getNashornGlobalFrom(ctxt));
}
- private ScriptFunction compileImpl(final Source source, final ScriptObject newGlobal) throws ScriptException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private ScriptFunction compileImpl(final Source source, final Global newGlobal) throws ScriptException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != newGlobal);
try {
if (globalChanged) {
@@ -607,7 +650,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return nashornContext.compileScript(source, newGlobal);
} catch (final Exception e) {
- throwAsScriptException(e);
+ throwAsScriptException(e, newGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
@@ -623,6 +666,11 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
continue;
}
+ // skip check for default methods - non-abstract, interface methods
+ if (! Modifier.isAbstract(method.getModifiers())) {
+ continue;
+ }
+
Object obj = sobj.get(method.getName());
if (! (obj instanceof ScriptFunction)) {
return false;
@@ -631,8 +679,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
return true;
}
- private static boolean isOfContext(final ScriptObject global, final Context context) {
- assert global instanceof GlobalObject: "Not a Global object";
- return ((GlobalObject)global).isOfContext(context);
+ private static boolean isOfContext(final Global global, final Context context) {
+ return global.isOfContext(context);
}
}
diff --git a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index 911f1663..b1255336 100644
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.scripting;
+import java.nio.ByteBuffer;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
@@ -41,9 +42,10 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.script.Bindings;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -62,7 +64,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
private static final AccessControlContext GET_CONTEXT_ACC_CTXT = getContextAccCtxt();
private final ScriptObject sobj;
- private final ScriptObject global;
+ private final Global global;
private final boolean strict;
@Override
@@ -93,7 +95,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public Object call(final Object thiz, final Object... args) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -108,6 +110,8 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
}
throw new RuntimeException("not a function: " + toString());
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -121,7 +125,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public Object newObject(final Object... args) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -135,6 +139,8 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
}
throw new RuntimeException("not a constructor: " + toString());
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -165,7 +171,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
public Object callMember(final String functionName, final Object... args) {
functionName.getClass(); // null check
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
@@ -182,6 +188,8 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
}
throw new NoSuchMethodException("No such function " + functionName);
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -253,6 +261,22 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
});
}
+ /**
+ * Nashorn extension: setIndexedPropertiesToExternalArrayData.
+ * set indexed properties be exposed from a given nio ByteBuffer.
+ *
+ * @param buf external buffer - should be a nio ByteBuffer
+ */
+ public void setIndexedPropertiesToExternalArrayData(final ByteBuffer buf) {
+ inGlobal(new Callable<Void>() {
+ @Override public Void call() {
+ sobj.setArray(ArrayData.allocate(buf));
+ return null;
+ }
+ });
+ }
+
+
@Override
public boolean isInstance(final Object obj) {
if (! (obj instanceof ScriptObjectMirror)) {
@@ -618,7 +642,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
*/
public static Object wrap(final Object obj, final Object homeGlobal) {
if(obj instanceof ScriptObject) {
- return homeGlobal instanceof ScriptObject ? new ScriptObjectMirror((ScriptObject)obj, (ScriptObject)homeGlobal) : obj;
+ return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj;
}
if(obj instanceof ConsString) {
return obj.toString();
@@ -686,13 +710,13 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
// package-privates below this.
- ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) {
+ ScriptObjectMirror(final ScriptObject sobj, final Global global) {
assert sobj != null : "ScriptObjectMirror on null!";
- assert global instanceof GlobalObject : "global is not a GlobalObject";
+ assert global != null : "home Global is null";
this.sobj = sobj;
this.global = global;
- this.strict = ((GlobalObject)global).isStrictContext();
+ this.strict = global.isStrictContext();
}
// accessors for script engine
@@ -700,7 +724,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
return sobj;
}
- ScriptObject getHomeGlobal() {
+ Global getHomeGlobal() {
return global;
}
@@ -710,13 +734,15 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
// internals only below this.
private <V> V inGlobal(final Callable<V> callable) {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
if (globalChanged) {
Context.setGlobal(global);
}
try {
return callable.call();
+ } catch (final NashornException ne) {
+ throw ne.initEcmaError(global);
} catch (final RuntimeException e) {
throw e;
} catch (final Exception e) {
diff --git a/src/jdk/nashorn/internal/codegen/Attr.java b/src/jdk/nashorn/internal/codegen/Attr.java
index 177cfef4..61ccb712 100644
--- a/src/jdk/nashorn/internal/codegen/Attr.java
+++ b/src/jdk/nashorn/internal/codegen/Attr.java
@@ -375,10 +375,11 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
* @return Symbol for given name or null for redefinition.
*/
private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
- int flags = symbolFlags;
- Symbol symbol = findSymbol(block, name); // Locate symbol.
+ int flags = symbolFlags;
+ Symbol symbol = findSymbol(block, name); // Locate symbol.
+ boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
- if ((flags & KINDMASK) == IS_GLOBAL) {
+ if (isGlobal) {
flags |= IS_SCOPE;
}
@@ -414,6 +415,8 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
// Determine where to create it.
if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
symbolBlock = block; //internal vars are always defined in the block closest to them
+ } else if (isGlobal) {
+ symbolBlock = lc.getOutermostFunction().getBody();
} else {
symbolBlock = lc.getFunctionBody(function);
}
diff --git a/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index c3b1dbe2..882846c6 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -685,7 +685,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private void scopeCall(final IdentNode node, final int flags) {
load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
// ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
- method.loadNull(); //the 'this'
+ method.loadUndefined(Type.OBJECT); //the 'this' object
method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
}
@@ -818,7 +818,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
protected boolean enterDefault(final Node node) {
// Load up function.
load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions
- method.loadNull(); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
+ method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
return false;
@@ -1451,7 +1451,10 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
if (value == null) {
hasGettersSetters = true;
- } else if (key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
+ } else if (propertyNode.getKey() instanceof IdentNode &&
+ key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
+ // ES6 draft compliant __proto__ inside object literal
+ // Identifier key and name is __proto__
protoNode = value;
continue;
}
@@ -2023,8 +2026,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
return false;
}
- method._new(ECMAException.class).dup();
-
final Source source = lc.getCurrentFunction().getSource();
final Expression expression = throwNode.getExpression();
@@ -2037,7 +2038,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
method.load(source.getName());
method.load(line);
method.load(column);
- method.invoke(ECMAException.THROW_INIT);
+ method.invoke(ECMAException.CREATE);
method.athrow();
@@ -3230,7 +3231,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
final String className = SCRIPTFUNCTION_IMPL_OBJECT;
final int fieldCount = ObjectClassGenerator.getPaddedFieldCount(functionNode.countThisProperties());
final String allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount));
- final PropertyMap allocatorMap = PropertyMap.newMap(null, 0, fieldCount, 0);
+ final PropertyMap allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
method._new(className).dup();
loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), allocatorClassName, allocatorMap));
diff --git a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index d27bdd95..dcf1b1ba 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -158,7 +158,7 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
if (scopeCalls.containsKey(scopeCall)) {
return scopeCalls.get(scopeCall);
}
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
scopeCalls.put(scopeCall, scopeCall);
return scopeCall;
}
@@ -177,7 +177,7 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
if (scopeCalls.containsKey(scopeCall)) {
return scopeCalls.get(scopeCall);
}
- scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName("scopeCall"));
+ scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
scopeCalls.put(scopeCall, scopeCall);
return scopeCall;
}
diff --git a/src/jdk/nashorn/internal/codegen/Compiler.java b/src/jdk/nashorn/internal/codegen/Compiler.java
index 24173c3e..e4af587b 100644
--- a/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -85,6 +85,8 @@ public final class Compiler {
private Source source;
+ private String sourceName;
+
private final Map<String, byte[]> bytecode;
private final Set<CompileUnit> compileUnits;
@@ -267,6 +269,7 @@ public final class Compiler {
append('$').
append(safeSourceName(functionNode.getSource()));
this.source = functionNode.getSource();
+ this.sourceName = functionNode.getSourceName();
this.scriptName = sb.toString();
}
@@ -402,32 +405,8 @@ public final class Compiler {
return newFunctionNode;
}
- private Class<?> install(final String className, final byte[] code) {
- LOG.fine("Installing class ", className);
-
- final Class<?> clazz = installer.install(Compiler.binaryName(className), code);
-
- try {
- final Object[] constants = getConstantData().toArray();
- // Need doPrivileged because these fields are private
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws Exception {
- //use reflection to write source and constants table to installed classes
- final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
- final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
- sourceField.setAccessible(true);
- constantsField.setAccessible(true);
- sourceField.set(null, source);
- constantsField.set(null, constants);
- return null;
- }
- });
- } catch (final PrivilegedActionException e) {
- throw new RuntimeException(e);
- }
-
- return clazz;
+ private Class<?> install(final String className, final byte[] code, final Object[] constants) {
+ return installer.install(className, code, source, constants);
}
/**
@@ -441,10 +420,15 @@ public final class Compiler {
assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
final Map<String, Class<?>> installedClasses = new HashMap<>();
+ final Object[] constants = getConstantData().toArray();
final String rootClassName = firstCompileUnitName();
final byte[] rootByteCode = bytecode.get(rootClassName);
- final Class<?> rootClass = install(rootClassName, rootByteCode);
+ final Class<?> rootClass = install(rootClassName, rootByteCode, constants);
+
+ if (!isLazy()) {
+ installer.storeCompiledScript(source, rootClassName, bytecode, constants);
+ }
int length = rootByteCode.length;
@@ -458,7 +442,7 @@ public final class Compiler {
final byte[] code = entry.getValue();
length += code.length;
- installedClasses.put(className, install(className, code));
+ installedClasses.put(className, install(className, code, constants));
}
for (final CompileUnit unit : compileUnits) {
@@ -573,7 +557,7 @@ public final class Compiler {
}
private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) {
- final ClassEmitter classEmitter = new ClassEmitter(env, source.getName(), unitClassName, strict);
+ final ClassEmitter classEmitter = new ClassEmitter(env, sourceName, unitClassName, strict);
final CompileUnit compileUnit = new CompileUnit(unitClassName, classEmitter, initialWeight);
classEmitter.begin();
diff --git a/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index fb347c75..16f08b82 100644
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -41,6 +41,7 @@ import jdk.nashorn.internal.runtime.Source;
*/
public enum CompilerConstants {
+
/** the __FILE__ variable */
__FILE__,
@@ -75,7 +76,7 @@ public enum CompilerConstants {
DEFAULT_SCRIPT_NAME("Script"),
/** function prefix for anonymous functions */
- FUNCTION_PREFIX("function$"),
+ ANON_FUNCTION_PREFIX("L:"),
/** method name for Java method that is script entry point */
RUN_SCRIPT("runScript"),
@@ -149,26 +150,31 @@ public enum CompilerConstants {
ALLOCATE("allocate"),
/** prefix for split methods, @see Splitter */
- SPLIT_PREFIX("$split"),
+ SPLIT_PREFIX(":split"),
/** prefix for split array method and slot */
- SPLIT_ARRAY_ARG("split_array", 3),
+ SPLIT_ARRAY_ARG(":split_array", 3),
/** get string from constant pool */
- GET_STRING("$getString"),
+ GET_STRING(":getString"),
/** get map */
- GET_MAP("$getMap"),
+ GET_MAP(":getMap"),
/** get map */
- SET_MAP("$setMap"),
+ SET_MAP(":setMap"),
/** get array prefix */
- GET_ARRAY_PREFIX("$get"),
+ GET_ARRAY_PREFIX(":get"),
/** get array suffix */
GET_ARRAY_SUFFIX("$array");
+ /**
+ * Prefix used for internal methods generated in script clases.
+ */
+ public static final String INTERNAL_METHOD_PREFIX = ":";
+
private final String symbolName;
private final Class<?> type;
private final int slot;
diff --git a/src/jdk/nashorn/internal/codegen/ConstantData.java b/src/jdk/nashorn/internal/codegen/ConstantData.java
index 631cdb3e..292f1678 100644
--- a/src/jdk/nashorn/internal/codegen/ConstantData.java
+++ b/src/jdk/nashorn/internal/codegen/ConstantData.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.codegen;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -110,6 +113,43 @@ class ConstantData {
}
/**
+ * {@link PropertyMap} wrapper class that provides implementations for the {@code hashCode} and {@code equals}
+ * methods that are based on the map layout. {@code PropertyMap} itself inherits the identity based implementations
+ * from {@code java.lang.Object}.
+ */
+ private static class PropertyMapWrapper {
+ private final PropertyMap propertyMap;
+ private final int hashCode;
+
+ public PropertyMapWrapper(final PropertyMap map) {
+ int hash = 0;
+ for (final Property property : map.getProperties()) {
+ hash = hash << 7 ^ hash >> 7;
+ hash ^= property.hashCode();
+ }
+ this.hashCode = hash;
+ this.propertyMap = map;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (!(other instanceof PropertyMapWrapper)) {
+ return false;
+ }
+
+ final Property[] ownProperties = propertyMap.getProperties();
+ final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
+
+ return Arrays.equals(ownProperties, otherProperties);
+ }
+ }
+
+ /**
* Constructor
*/
ConstantData() {
@@ -145,7 +185,14 @@ class ConstantData {
* @return the index in the constant pool that the object was given
*/
public int add(final Object object) {
- final Object entry = object.getClass().isArray() ? new ArrayWrapper(object) : object;
+ final Object entry;
+ if (object.getClass().isArray()) {
+ entry = new ArrayWrapper(object);
+ } else if (object instanceof PropertyMap) {
+ entry = new PropertyMapWrapper((PropertyMap) object);
+ } else {
+ entry = object;
+ }
final Integer value = objectMap.get(entry);
if (value != null) {
diff --git a/src/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk/nashorn/internal/codegen/MapCreator.java
index 8012adf5..436622bd 100644
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/src/jdk/nashorn/internal/codegen/MapCreator.java
@@ -83,7 +83,7 @@ public class MapCreator {
}
}
- return PropertyMap.newMap(properties, fieldCount, fieldMaximum, 0);
+ return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0);
}
PropertyMap makeSpillMap(final boolean hasArguments) {
@@ -100,7 +100,7 @@ public class MapCreator {
}
}
- return PropertyMap.newMap(properties, 0, 0, spillIndex);
+ return PropertyMap.newMap(properties, structure.getName(), 0, 0, spillIndex);
}
/**
diff --git a/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index 9b6d12aa..91129ece 100644
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -1130,7 +1130,11 @@ public class MethodEmitter implements Emitter {
popType(Type.OBJECT);
}
- method.visitMethodInsn(opcode, className, methodName, methodDescriptor);
+ if (opcode == INVOKEINTERFACE) {
+ method.visitMethodInsn(opcode, className, methodName, methodDescriptor, true);
+ } else {
+ method.visitMethodInsn(opcode, className, methodName, methodDescriptor, false);
+ }
if (returnType != null) {
pushType(returnType);
diff --git a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
index c7dfb40a..da29ac05 100644
--- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
+++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@@ -156,7 +156,7 @@ class SharedScopeCall {
if (isCall) {
method.convert(Type.OBJECT);
// ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
- method.loadNull();
+ method.loadUndefined(Type.OBJECT);
int slot = 2;
for (final Type type : paramTypes) {
method.load(type, slot++);
diff --git a/src/jdk/nashorn/internal/codegen/types/Type.java b/src/jdk/nashorn/internal/codegen/types/Type.java
index e7c78953..4799c264 100644
--- a/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -261,7 +261,7 @@ public abstract class Type implements Comparable<Type>, BytecodeOps {
}
static void invokeStatic(final MethodVisitor method, final Call call) {
- method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor());
+ method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor(), false);
}
/**
diff --git a/src/jdk/nashorn/internal/ir/FunctionNode.java b/src/jdk/nashorn/internal/ir/FunctionNode.java
index b0998ae1..a0f6a788 100644
--- a/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -29,6 +29,7 @@ import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.Compiler;
@@ -138,6 +139,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Function flags. */
private final int flags;
+ /** //@ sourceURL or //# sourceURL for program function nodes */
+ private final String sourceURL;
+
private final int lineNumber;
/** Is anonymous function flag. */
@@ -160,11 +164,11 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
public static final int HAS_EVAL = 1 << 5;
/** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
- public static final int HAS_NESTED_EVAL = 1 << 6;
+ public static final int HAS_NESTED_EVAL = 1 << 6;
/** Does this function have any blocks that create a scope? This is used to determine if the function needs to
* have a local variable slot for the scope symbol. */
- public static final int HAS_SCOPE_BLOCK = 1 << 7;
+ public static final int HAS_SCOPE_BLOCK = 1 << 7;
/**
* Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
@@ -193,6 +197,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Can this function be specialized? */
public static final int CAN_SPECIALIZE = 1 << 14;
+ /** Does this function use the "this" keyword? */
+ public static final int USES_THIS = 1 << 15;
+
/** Does this function or any nested functions contain an eval? */
private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
@@ -223,6 +230,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @param parameters parameter list
* @param kind kind of function as in {@link FunctionNode.Kind}
* @param flags initial flags
+ * @param sourceURL sourceURL specified in script (optional)
*/
public FunctionNode(
final Source source,
@@ -235,7 +243,8 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
final String name,
final List<IdentNode> parameters,
final FunctionNode.Kind kind,
- final int flags) {
+ final int flags,
+ final String sourceURL) {
super(token, finish);
this.source = source;
@@ -250,6 +259,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
this.declaredSymbols = new HashSet<>();
this.flags = flags;
+ this.sourceURL = sourceURL;
this.compileUnit = null;
this.body = null;
this.snapshot = null;
@@ -260,6 +270,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
final FunctionNode functionNode,
final long lastToken,
final int flags,
+ final String sourceURL,
final String name,
final Type returnType,
final CompileUnit compileUnit,
@@ -271,6 +282,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
super(functionNode);
this.lineNumber = functionNode.lineNumber;
this.flags = flags;
+ this.sourceURL = sourceURL;
this.name = name;
this.returnType = returnType;
this.compileUnit = compileUnit;
@@ -308,6 +320,38 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
+ * get source name - sourceURL or name derived from Source.
+ *
+ * @return name for the script source
+ */
+ public String getSourceName() {
+ return (sourceURL != null)? sourceURL : source.getName();
+ }
+
+ /**
+ * get the sourceURL
+ * @return the sourceURL
+ */
+ public String getSourceURL() {
+ return sourceURL;
+ }
+
+ /**
+ * Set the sourceURL
+ *
+ * @param lc lexical context
+ * @param newSourceURL source url string to set
+ * @return function node or a new one if state was changed
+ */
+ public FunctionNode setSourceURL(final LexicalContext lc, final String newSourceURL) {
+ if (Objects.equals(sourceURL, newSourceURL)) {
+ return this;
+ }
+
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, newSourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ }
+
+ /**
* Returns the line number.
* @return the line number.
*/
@@ -335,7 +379,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.snapshot == null) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
}
/**
@@ -351,7 +395,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (isProgram() || parameters.isEmpty()) {
return this; //never specialize anything that won't be recompiled
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
}
/**
@@ -409,7 +453,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
newState.add(state);
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
}
/**
@@ -430,7 +474,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.hints == hints) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -483,7 +527,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.flags == flags) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
@Override
@@ -550,6 +594,15 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
/**
+ * Return {@code true} if this function makes use of the {@code this} object.
+ *
+ * @return true if function uses {@code this} object
+ */
+ public boolean usesThis() {
+ return getFlag(USES_THIS);
+ }
+
+ /**
* Get the identifier for this function, this is its symbol.
* @return the identifier as an IdentityNode
*/
@@ -593,7 +646,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if(this.body == body) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -688,7 +741,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.lastToken == lastToken) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -710,7 +763,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.name.equals(name)) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -760,7 +813,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.parameters == parameters) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
@@ -825,6 +878,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this,
lastToken,
flags,
+ sourceURL,
name,
type,
compileUnit,
@@ -863,7 +917,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
if (this.compileUnit == compileUnit) {
return this;
}
- return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+ return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/**
diff --git a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
index 4702057a..ef7f8a1b 100644
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.ir.debug;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
@@ -88,7 +90,7 @@ public final class JSONWriter extends NodeVisitor<LexicalContext> {
* @return JSON string representation of AST of the supplied code
*/
public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) {
- final Parser parser = new Parser(env, new Source(name, code), new Context.ThrowErrorManager(), env._strict);
+ final Parser parser = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict);
final JSONWriter jsonWriter = new JSONWriter(includeLoc);
try {
final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName());
diff --git a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index b3731620..e39c5217 100644
--- a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -67,12 +67,8 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) {
- super(global.getObjectPrototype(), global.getAccessorPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
this.get = get;
@@ -185,6 +181,18 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor otherDesc) {
+ if (! (otherDesc instanceof AccessorPropertyDescriptor)) {
+ return false;
+ }
+ final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)otherDesc;
+ return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) &&
+ (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) &&
+ (!has(GET) || sameValue(get, other.get)) &&
+ (!has(SET) || sameValue(set, other.set));
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index ecf8bec8..c29af851 100644
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -42,12 +42,8 @@ abstract class ArrayBufferView extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
- super(global.getArrayBufferViewMap());
+ super($nasgenmap$);
checkConstructorArgs(buffer, byteOffset, elementLength);
this.setProto(getPrototype(global));
this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
@@ -386,7 +382,7 @@ abstract class ArrayBufferView extends ScriptObject {
return (int) (length & Integer.MAX_VALUE);
}
- protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
+ protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
final ArrayBufferView arrayView = ((ArrayBufferView)self);
final int elementLength = arrayView.elementLength();
final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
diff --git a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index ef3f0a30..e117c7ed 100644
--- a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -64,12 +64,8 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
DataPropertyDescriptor(final boolean configurable, final boolean enumerable, final boolean writable, final Object value, final Global global) {
- super(global.getObjectPrototype(), global.getDataPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
this.writable = writable;
@@ -172,6 +168,19 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor otherDesc) {
+ if (! (otherDesc instanceof DataPropertyDescriptor)) {
+ return false;
+ }
+
+ final DataPropertyDescriptor other = (DataPropertyDescriptor)otherDesc;
+ return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) &&
+ (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) &&
+ (!has(WRITABLE) || sameValue(writable, other.writable)) &&
+ (!has(VALUE) || sameValue(value, other.value));
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index f5662efa..19cc8b6f 100644
--- a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -55,12 +55,8 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
GenericPropertyDescriptor(final boolean configurable, final boolean enumerable, final Global global) {
- super(global.getObjectPrototype(), global.getGenericPropertyDescriptorMap());
+ super(global.getObjectPrototype(), $nasgenmap$);
this.configurable = configurable;
this.enumerable = enumerable;
}
@@ -149,6 +145,23 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro
}
@Override
+ public boolean hasAndEquals(final PropertyDescriptor other) {
+ if (has(CONFIGURABLE) && other.has(CONFIGURABLE)) {
+ if (isConfigurable() != other.isConfigurable()) {
+ return false;
+ }
+ }
+
+ if (has(ENUMERABLE) && other.has(ENUMERABLE)) {
+ if (isEnumerable() != other.isEnumerable()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java
index db79f5f9..00019382 100644
--- a/src/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk/nashorn/internal/objects/Global.java
@@ -33,11 +33,8 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
@@ -51,7 +48,6 @@ import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.GlobalFunctions;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
@@ -59,10 +55,10 @@ import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
-import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -73,7 +69,7 @@ import jdk.nashorn.internal.scripts.JO;
* Representation of global scope.
*/
@ScriptClass("Global")
-public final class Global extends ScriptObject implements GlobalObject, Scope {
+public final class Global extends ScriptObject implements Scope {
private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
private final InvokeByName VALUE_OF = new InvokeByName("valueOf", ScriptObject.class);
@@ -229,6 +225,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
@Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
public volatile Object arrayBuffer;
+ /** DataView object */
+ @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
+ public volatile Object dataView;
+
/** TypedArray (int8) */
@Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
public volatile Object int8Array;
@@ -355,6 +355,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private ScriptObject builtinJavaImporter;
private ScriptObject builtinJavaApi;
private ScriptObject builtinArrayBuffer;
+ private ScriptObject builtinDataView;
private ScriptObject builtinInt8Array;
private ScriptObject builtinUint8Array;
private ScriptObject builtinUint8ClampedArray;
@@ -370,42 +371,9 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
*/
private ScriptFunction typeErrorThrower;
- private PropertyMap accessorPropertyDescriptorMap;
- private PropertyMap arrayBufferViewMap;
- private PropertyMap dataPropertyDescriptorMap;
- private PropertyMap genericPropertyDescriptorMap;
- private PropertyMap nativeArgumentsMap;
- private PropertyMap nativeArrayMap;
- private PropertyMap nativeArrayBufferMap;
- private PropertyMap nativeBooleanMap;
- private PropertyMap nativeDateMap;
- private PropertyMap nativeErrorMap;
- private PropertyMap nativeEvalErrorMap;
- private PropertyMap nativeJSAdapterMap;
- private PropertyMap nativeJavaImporterMap;
- private PropertyMap nativeNumberMap;
- private PropertyMap nativeRangeErrorMap;
- private PropertyMap nativeReferenceErrorMap;
- private PropertyMap nativeRegExpMap;
- private PropertyMap nativeRegExpExecResultMap;
- private PropertyMap nativeStrictArgumentsMap;
- private PropertyMap nativeStringMap;
- private PropertyMap nativeSyntaxErrorMap;
- private PropertyMap nativeTypeErrorMap;
- private PropertyMap nativeURIErrorMap;
- private PropertyMap prototypeObjectMap;
- private PropertyMap objectMap;
- private PropertyMap functionMap;
- private PropertyMap anonymousFunctionMap;
- private PropertyMap strictFunctionMap;
- private PropertyMap boundFunctionMap;
-
// Flag to indicate that a split method issued a return statement
private int splitState = -1;
- // class cache
- private ClassCache classCache;
-
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
@@ -456,11 +424,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
-
- final int cacheSize = context.getEnv()._class_cache_size;
- if (cacheSize > 0) {
- classCache = new ClassCache(cacheSize);
- }
}
/**
@@ -469,11 +432,9 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* @return the global singleton
*/
public static Global instance() {
- ScriptObject global = Context.getGlobal();
- if (! (global instanceof Global)) {
- throw new IllegalStateException("no current global instance");
- }
- return (Global)global;
+ Global global = Context.getGlobal();
+ global.getClass(); // null check
+ return global;
}
/**
@@ -494,19 +455,30 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return instance().getContext();
}
- // GlobalObject interface implementation
+ // Runtime interface to Global
- @Override
+ /**
+ * Is this global of the given Context?
+ * @param ctxt the context
+ * @return true if this global belongs to the given Context
+ */
public boolean isOfContext(final Context ctxt) {
return this.context == ctxt;
}
- @Override
+ /**
+ * Does this global belong to a strict Context?
+ * @return true if this global belongs to a strict Context
+ */
public boolean isStrictContext() {
return context.getEnv()._strict;
}
- @Override
+ /**
+ * Initialize standard builtin objects like "Object", "Array", "Function" etc.
+ * as well as our extension builtin objects like "Java", "JSAdapter" as properties
+ * of the global scope object.
+ */
public void initBuiltinObjects() {
if (this.builtinObject != null) {
// already initialized, just return
@@ -516,12 +488,26 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
init();
}
- @Override
+ /**
+ * Create a new ScriptFunction object
+ *
+ * @param name function name
+ * @param handle invocation handle for function
+ * @param scope the scope
+ * @param strict are we in strict mode
+ *
+ * @return new script function
+ */
public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
- return new ScriptFunctionImpl(name, handle, scope, null, strict, false, true);
+ return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
}
- @Override
+ /**
+ * Wrap a Java object as corresponding script object
+ *
+ * @param obj object to wrap
+ * @return wrapped object
+ */
public Object wrapAsObject(final Object obj) {
if (obj instanceof Boolean) {
return new NativeBoolean((Boolean)obj, this);
@@ -543,7 +529,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
}
}
- @Override
+ /**
+ * Lookup helper for JS primitive types
+ *
+ * @param request the link request for the dynamic call site.
+ * @param self self reference
+ *
+ * @return guarded invocation
+ */
public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
if (self instanceof String || self instanceof ConsString) {
return NativeString.lookupPrimitive(request, self);
@@ -555,12 +548,23 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
throw new IllegalArgumentException("Unsupported primitive: " + self);
}
- @Override
+ /**
+ * Create a new empty script object
+ *
+ * @return the new ScriptObject
+ */
public ScriptObject newObject() {
- return new JO(getObjectPrototype(), getObjectMap());
+ return new JO(getObjectPrototype(), JO.getInitialMap());
}
- @Override
+ /**
+ * Default value of given type
+ *
+ * @param sobj script object
+ * @param typeHint type hint
+ *
+ * @return default value
+ */
public Object getDefaultValue(final ScriptObject sobj, final Class<?> typeHint) {
// When the [[DefaultValue]] internal method of O is called with no hint,
// then it behaves as if the hint were Number, unless O is a Date object
@@ -620,7 +624,12 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return UNDEFINED;
}
- @Override
+ /**
+ * Is the given ScriptObject an ECMAScript Error object?
+ *
+ * @param sobj the object being checked
+ * @return true if sobj is an Error object
+ */
public boolean isError(final ScriptObject sobj) {
final ScriptObject errorProto = getErrorPrototype();
ScriptObject proto = sobj.getProto();
@@ -633,52 +642,108 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return false;
}
- @Override
+ /**
+ * Create a new ECMAScript Error object.
+ *
+ * @param msg error message
+ * @return newly created Error object
+ */
public ScriptObject newError(final String msg) {
return new NativeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript EvalError object.
+ *
+ * @param msg error message
+ * @return newly created EvalError object
+ */
public ScriptObject newEvalError(final String msg) {
return new NativeEvalError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript RangeError object.
+ *
+ * @param msg error message
+ * @return newly created RangeError object
+ */
public ScriptObject newRangeError(final String msg) {
return new NativeRangeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript ReferenceError object.
+ *
+ * @param msg error message
+ * @return newly created ReferenceError object
+ */
public ScriptObject newReferenceError(final String msg) {
return new NativeReferenceError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript SyntaxError object.
+ *
+ * @param msg error message
+ * @return newly created SyntaxError object
+ */
public ScriptObject newSyntaxError(final String msg) {
return new NativeSyntaxError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript TypeError object.
+ *
+ * @param msg error message
+ * @return newly created TypeError object
+ */
public ScriptObject newTypeError(final String msg) {
return new NativeTypeError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript URIError object.
+ *
+ * @param msg error message
+ * @return newly created URIError object
+ */
public ScriptObject newURIError(final String msg) {
return new NativeURIError(msg, this);
}
- @Override
+ /**
+ * Create a new ECMAScript GenericDescriptor object.
+ *
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created GenericDescriptor object
+ */
public PropertyDescriptor newGenericDescriptor(final boolean configurable, final boolean enumerable) {
return new GenericPropertyDescriptor(configurable, enumerable, this);
}
- @Override
+ /**
+ * Create a new ECMAScript DatePropertyDescriptor object.
+ *
+ * @param value of the data property
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created DataPropertyDescriptor object
+ */
public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
return new DataPropertyDescriptor(configurable, enumerable, writable, value, this);
}
- @Override
+ /**
+ * Create a new ECMAScript AccessorPropertyDescriptor object.
+ *
+ * @param get getter function of the user accessor property
+ * @param set setter function of the user accessor property
+ * @param configurable is the property configurable?
+ * @param enumerable is the property enumerable?
+ * @return newly created AccessorPropertyDescriptor object
+ */
public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set, this);
@@ -694,62 +759,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
}
- /**
- * Cache for compiled script classes.
- */
- @SuppressWarnings("serial")
- private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
- private final int size;
- private final ReferenceQueue<Class<?>> queue;
-
- ClassCache(int size) {
- super(size, 0.75f, true);
- this.size = size;
- this.queue = new ReferenceQueue<>();
- }
-
- void cache(final Source source, final Class<?> clazz) {
- put(source, new ClassReference(clazz, queue, source));
- }
-
- @Override
- protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
- return size() > size;
- }
-
- @Override
- public ClassReference get(Object key) {
- for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
- remove(ref.source);
- }
- return super.get(key);
- }
-
- }
-
- private static class ClassReference extends SoftReference<Class<?>> {
- private final Source source;
-
- ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
- super(clazz, queue);
- this.source = source;
- }
- }
-
- // Class cache management
- @Override
- public Class<?> findCachedClass(final Source source) {
- assert classCache != null : "Class cache used without being initialized";
- ClassReference ref = classCache.get(source);
- return ref != null ? ref.get() : null;
- }
-
- @Override
- public void cacheClass(final Source source, final Class<?> clazz) {
- assert classCache != null : "Class cache used without being initialized";
- classCache.cache(source, clazz);
- }
-
private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
final T obj = map.get(key);
if (obj != null) {
@@ -767,14 +776,25 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private final Map<Object, InvokeByName> namedInvokers = new ConcurrentHashMap<>();
- @Override
+
+ /**
+ * Get cached InvokeByName object for the given key
+ * @param key key to be associated with InvokeByName object
+ * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
+ * @return InvokeByName object associated with the key.
+ */
public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator) {
return getLazilyCreatedValue(key, creator, namedInvokers);
}
private final Map<Object, MethodHandle> dynamicInvokers = new ConcurrentHashMap<>();
- @Override
+ /**
+ * Get cached dynamic method handle for the given key
+ * @param key key to be associated with dynamic method handle
+ * @param creator if method handle is absent 'creator' is called to make one (lazy init)
+ * @return dynamic method handle associated with the key.
+ */
public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
return getLazilyCreatedValue(key, creator, dynamicInvokers);
}
@@ -963,6 +983,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return ScriptFunction.getPrototype(builtinArrayBuffer);
}
+ ScriptObject getDataViewPrototype() {
+ return ScriptFunction.getPrototype(builtinDataView);
+ }
+
ScriptObject getInt8ArrayPrototype() {
return ScriptFunction.getPrototype(builtinInt8Array);
}
@@ -999,123 +1023,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return ScriptFunction.getPrototype(builtinFloat64Array);
}
- // Builtin PropertyMap accessors
- PropertyMap getAccessorPropertyDescriptorMap() {
- return accessorPropertyDescriptorMap;
- }
-
- PropertyMap getArrayBufferViewMap() {
- return arrayBufferViewMap;
- }
-
- PropertyMap getDataPropertyDescriptorMap() {
- return dataPropertyDescriptorMap;
- }
-
- PropertyMap getGenericPropertyDescriptorMap() {
- return genericPropertyDescriptorMap;
- }
-
- PropertyMap getArgumentsMap() {
- return nativeArgumentsMap;
- }
-
- PropertyMap getArrayMap() {
- return nativeArrayMap;
- }
-
- PropertyMap getArrayBufferMap() {
- return nativeArrayBufferMap;
- }
-
- PropertyMap getBooleanMap() {
- return nativeBooleanMap;
- }
-
- PropertyMap getDateMap() {
- return nativeDateMap;
- }
-
- PropertyMap getErrorMap() {
- return nativeErrorMap;
- }
-
- PropertyMap getEvalErrorMap() {
- return nativeEvalErrorMap;
- }
-
- PropertyMap getJSAdapterMap() {
- return nativeJSAdapterMap;
- }
-
- PropertyMap getJavaImporterMap() {
- return nativeJavaImporterMap;
- }
-
- PropertyMap getNumberMap() {
- return nativeNumberMap;
- }
-
- PropertyMap getRangeErrorMap() {
- return nativeRangeErrorMap;
- }
-
- PropertyMap getReferenceErrorMap() {
- return nativeReferenceErrorMap;
- }
-
- PropertyMap getRegExpMap() {
- return nativeRegExpMap;
- }
-
- PropertyMap getRegExpExecResultMap() {
- return nativeRegExpExecResultMap;
- }
-
- PropertyMap getStrictArgumentsMap() {
- return nativeStrictArgumentsMap;
- }
-
- PropertyMap getStringMap() {
- return nativeStringMap;
- }
-
- PropertyMap getSyntaxErrorMap() {
- return nativeSyntaxErrorMap;
- }
-
- PropertyMap getTypeErrorMap() {
- return nativeTypeErrorMap;
- }
-
- PropertyMap getURIErrorMap() {
- return nativeURIErrorMap;
- }
-
- PropertyMap getPrototypeObjectMap() {
- return prototypeObjectMap;
- }
-
- PropertyMap getObjectMap() {
- return objectMap;
- }
-
- PropertyMap getFunctionMap() {
- return functionMap;
- }
-
- PropertyMap getAnonymousFunctionMap() {
- return anonymousFunctionMap;
- }
-
- PropertyMap getStrictFunctionMap() {
- return strictFunctionMap;
- }
-
- PropertyMap getBoundFunctionMap() {
- return boundFunctionMap;
- }
-
private ScriptFunction getBuiltinArray() {
return builtinArray;
}
@@ -1631,14 +1538,11 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
final ScriptEnvironment env = getContext().getEnv();
- // duplicate PropertyMaps of Native* classes
- copyInitialMaps(env);
-
// initialize Function and Object constructor
initFunctionAndObject();
// Now fix Global's own proto.
- this.setProto(getObjectPrototype());
+ this.setInitialProto(getObjectPrototype());
// initialize global function properties
this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
@@ -1705,8 +1609,25 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
initScripting(env);
}
- if (Context.DEBUG && System.getSecurityManager() == null) {
- initDebug();
+ if (Context.DEBUG) {
+ boolean debugOkay;
+ final SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkPermission(new RuntimePermission(Context.NASHORN_DEBUG_MODE));
+ debugOkay = true;
+ } catch (final SecurityException ignored) {
+ // if no permission, don't initialize Debug object
+ debugOkay = false;
+ }
+
+ } else {
+ debugOkay = true;
+ }
+
+ if (debugOkay) {
+ initDebug();
+ }
}
copyBuiltins();
@@ -1766,7 +1687,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
prototype.set(NativeError.NAME, name, false);
prototype.set(NativeError.MESSAGE, "", false);
- prototype.setProto(errorProto);
+ prototype.setInitialProto(errorProto);
return (ScriptFunction)cons;
}
@@ -1834,6 +1755,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private void initTypedArray() {
this.builtinArrayBuffer = initConstructor("ArrayBuffer");
+ this.builtinDataView = initConstructor("DataView");
this.builtinInt8Array = initConstructor("Int8Array");
this.builtinUint8Array = initConstructor("Uint8Array");
this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
@@ -1874,6 +1796,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
this.typeError = this.builtinTypeError;
this.uriError = this.builtinURIError;
this.arrayBuffer = this.builtinArrayBuffer;
+ this.dataView = this.builtinDataView;
this.int8Array = this.builtinInt8Array;
this.uint8Array = this.builtinUint8Array;
this.uint8ClampedArray = this.builtinUint8ClampedArray;
@@ -1938,7 +1861,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
}
if (res.getProto() == null) {
- res.setProto(getObjectPrototype());
+ res.setInitialProto(getObjectPrototype());
}
return res;
@@ -1948,46 +1871,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
}
}
- private void copyInitialMaps(final ScriptEnvironment env) {
- this.accessorPropertyDescriptorMap = AccessorPropertyDescriptor.getInitialMap().duplicate();
- this.dataPropertyDescriptorMap = DataPropertyDescriptor.getInitialMap().duplicate();
- this.genericPropertyDescriptorMap = GenericPropertyDescriptor.getInitialMap().duplicate();
- this.nativeArgumentsMap = NativeArguments.getInitialMap().duplicate();
- this.nativeArrayMap = NativeArray.getInitialMap().duplicate();
- this.nativeBooleanMap = NativeBoolean.getInitialMap().duplicate();
- this.nativeDateMap = NativeDate.getInitialMap().duplicate();
- this.nativeErrorMap = NativeError.getInitialMap().duplicate();
- this.nativeEvalErrorMap = NativeEvalError.getInitialMap().duplicate();
- this.nativeJSAdapterMap = NativeJSAdapter.getInitialMap().duplicate();
- this.nativeNumberMap = NativeNumber.getInitialMap().duplicate();
- this.nativeRangeErrorMap = NativeRangeError.getInitialMap().duplicate();
- this.nativeReferenceErrorMap = NativeReferenceError.getInitialMap().duplicate();
- this.nativeRegExpMap = NativeRegExp.getInitialMap().duplicate();
- this.nativeRegExpExecResultMap = NativeRegExpExecResult.getInitialMap().duplicate();
- this.nativeStrictArgumentsMap = NativeStrictArguments.getInitialMap().duplicate();
- this.nativeStringMap = NativeString.getInitialMap().duplicate();
- this.nativeSyntaxErrorMap = NativeSyntaxError.getInitialMap().duplicate();
- this.nativeTypeErrorMap = NativeTypeError.getInitialMap().duplicate();
- this.nativeURIErrorMap = NativeURIError.getInitialMap().duplicate();
- this.prototypeObjectMap = PrototypeObject.getInitialMap().duplicate();
- this.objectMap = JO.getInitialMap().duplicate();
- this.functionMap = ScriptFunctionImpl.getInitialMap().duplicate();
- this.anonymousFunctionMap = ScriptFunctionImpl.getInitialAnonymousMap().duplicate();
- this.strictFunctionMap = ScriptFunctionImpl.getInitialStrictMap().duplicate();
- this.boundFunctionMap = ScriptFunctionImpl.getInitialBoundMap().duplicate();
-
- // java
- if (! env._no_java) {
- this.nativeJavaImporterMap = NativeJavaImporter.getInitialMap().duplicate();
- }
-
- // typed arrays
- if (! env._no_typed_arrays) {
- this.arrayBufferViewMap = ArrayBufferView.getInitialMap().duplicate();
- this.nativeArrayBufferMap = NativeArrayBuffer.getInitialMap().duplicate();
- }
- }
-
// Function and Object constructors are inter-dependent. Also,
// Function.prototype
// functions are not properly initialized. We fix the references here.
@@ -2005,13 +1888,13 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
// Function.prototype === Object.getPrototypeOf(Function) ===
// <anon-function>
- builtinFunction.setProto(anon);
+ builtinFunction.setInitialProto(anon);
builtinFunction.setPrototype(anon);
anon.set("constructor", builtinFunction, false);
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
- this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, false, false, false);
+ this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
typeErrorThrower.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
@@ -2021,7 +1904,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
this.builtinObject = (ScriptFunction)initConstructor("Object");
final ScriptObject ObjectPrototype = getObjectPrototype();
// Object.getPrototypeOf(Function.prototype) === Object.prototype
- anon.setProto(ObjectPrototype);
+ anon.setInitialProto(ObjectPrototype);
+
+ // ES6 draft compliant __proto__ property of Object.prototype
+ // accessors on Object.prototype for "__proto__"
+ final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", ScriptObject.GETPROTO);
+ final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", ScriptObject.SETPROTOCHECK);
+ ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
+
// Function valued properties of Function.prototype were not properly
// initialized. Because, these were created before global.function and
@@ -2033,10 +1923,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
if (value instanceof ScriptFunction && value != anon) {
final ScriptFunction func = (ScriptFunction)value;
- func.setProto(getFunctionPrototype());
+ func.setInitialProto(getFunctionPrototype());
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
@@ -2051,7 +1941,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
@@ -2069,7 +1959,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
final ScriptFunction func = (ScriptFunction)value;
final ScriptObject prototype = ScriptFunction.getPrototype(func);
if (prototype != null) {
- prototype.setProto(ObjectPrototype);
+ prototype.setInitialProto(ObjectPrototype);
}
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeArguments.java b/src/jdk/nashorn/internal/objects/NativeArguments.java
index f8535732..03f68bf6 100644
--- a/src/jdk/nashorn/internal/objects/NativeArguments.java
+++ b/src/jdk/nashorn/internal/objects/NativeArguments.java
@@ -68,7 +68,7 @@ public final class NativeArguments extends ScriptObject {
final ArrayList<Property> properties = new ArrayList<>(2);
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
properties.add(AccessorProperty.create("callee", Property.NOT_ENUMERABLE, G$CALLEE, S$CALLEE));
- map$ = PropertyMap.newMap(properties).setIsShared();
+ map$ = PropertyMap.newMap(properties);
}
static PropertyMap getInitialMap() {
@@ -267,9 +267,9 @@ public final class NativeArguments extends ScriptObject {
final Global global = Global.instance();
final ScriptObject proto = global.getObjectPrototype();
if (isStrict) {
- return new NativeStrictArguments(arguments, numParams, proto, global.getStrictArgumentsMap());
+ return new NativeStrictArguments(arguments, numParams, proto, NativeStrictArguments.getInitialMap());
}
- return new NativeArguments(arguments, callee, numParams, proto, global.getArgumentsMap());
+ return new NativeArguments(arguments, callee, numParams, proto, NativeArguments.getInitialMap());
}
/**
diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java
index 67b9f1f1..6f07cb9d 100644
--- a/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -31,6 +31,7 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle;
import java.util.ArrayList;
@@ -156,10 +157,6 @@ public final class NativeArray extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
/*
* Constructors.
*/
@@ -208,7 +205,7 @@ public final class NativeArray extends ScriptObject {
}
NativeArray(final ArrayData arrayData, final Global global) {
- super(global.getArrayPrototype(), global.getArrayMap());
+ super(global.getArrayPrototype(), $nasgenmap$);
this.setArray(arrayData);
this.setIsArray();
}
@@ -354,6 +351,27 @@ public final class NativeArray extends ScriptObject {
}
/**
+ * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
+ * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
+ * method in such cases. This is because set method uses inherited setters (if any)
+ * from any object in proto chain such as Array.prototype, Object.prototype.
+ * This method directly sets a particular element value in the current object.
+ *
+ * @param index key for property
+ * @param value value to define
+ */
+ @Override
+ public final void defineOwnProperty(final int index, final Object value) {
+ assert isValidArrayIndex(index) : "invalid array index";
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (longIndex >= getArray().length()) {
+ // make array big enough to hold..
+ setArray(getArray().ensure(longIndex));
+ }
+ setArray(getArray().set(index, value, false));
+ }
+
+ /**
* Return the array contents upcasted as an ObjectArray, regardless of
* representation
*
@@ -371,7 +389,7 @@ public final class NativeArray extends ScriptObject {
* @return true if argument is an array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isArray(final Object self, final Object arg) {
+ public static boolean isArray(final Object self, final Object arg) {
return isArray(arg) || (arg instanceof JSObject && ((JSObject)arg).isArray());
}
@@ -470,7 +488,7 @@ public final class NativeArray extends ScriptObject {
* @return locale specific string representation for array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = arrayLikeIterator(self, true);
@@ -516,7 +534,7 @@ public final class NativeArray extends ScriptObject {
* @return the new NativeArray
*/
@Constructor(arity = 1)
- public static Object construct(final boolean newObj, final Object self, final Object... args) {
+ public static NativeArray construct(final boolean newObj, final Object self, final Object... args) {
switch (args.length) {
case 0:
return new NativeArray(0);
@@ -569,7 +587,7 @@ public final class NativeArray extends ScriptObject {
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self) {
+ public static NativeArray construct(final boolean newObj, final Object self) {
return new NativeArray(0);
}
@@ -584,7 +602,7 @@ public final class NativeArray extends ScriptObject {
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final int length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final int length) {
if (length >= 0) {
return new NativeArray(length);
}
@@ -603,7 +621,7 @@ public final class NativeArray extends ScriptObject {
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final long length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final long length) {
if (length >= 0L && length <= JSType.MAX_UINT) {
return new NativeArray(length);
}
@@ -622,7 +640,7 @@ public final class NativeArray extends ScriptObject {
* @return the new NativeArray
*/
@SpecializedConstructor
- public static Object construct(final boolean newObj, final Object self, final double length) {
+ public static NativeArray construct(final boolean newObj, final Object self, final double length) {
final long uint32length = JSType.toUint32(length);
if (uint32length == length) {
@@ -640,7 +658,7 @@ public final class NativeArray extends ScriptObject {
* @return resulting NativeArray
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object concat(final Object self, final Object... args) {
+ public static NativeArray concat(final Object self, final Object... args) {
final ArrayList<Object> list = new ArrayList<>();
concatToList(list, Global.toObject(self));
@@ -687,7 +705,7 @@ public final class NativeArray extends ScriptObject {
* @return string representation after join
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object join(final Object self, final Object separator) {
+ public static String join(final Object self, final Object separator) {
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = arrayLikeIterator(self, true);
final String sep = separator == ScriptRuntime.UNDEFINED ? "," : JSType.toString(separator);
@@ -955,7 +973,7 @@ public final class NativeArray extends ScriptObject {
* @return sorted array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object sort(final Object self, final Object comparefn) {
+ public static ScriptObject sort(final Object self, final Object comparefn) {
try {
final ScriptObject sobj = (ScriptObject) self;
final long len = JSType.toUint32(sobj.getLength());
@@ -1159,7 +1177,7 @@ public final class NativeArray extends ScriptObject {
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object indexOf(final Object self, final Object searchElement, final Object fromIndex) {
+ public static long indexOf(final Object self, final Object searchElement, final Object fromIndex) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
@@ -1195,7 +1213,7 @@ public final class NativeArray extends ScriptObject {
* @return index of element, or -1 if not found
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object lastIndexOf(final Object self, final Object... args) {
+ public static long lastIndexOf(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)Global.toObject(self);
final long len = JSType.toUint32(sobj.getLength());
@@ -1230,7 +1248,7 @@ public final class NativeArray extends ScriptObject {
* @return true if callback function return true for every element in the array, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object every(final Object self, final Object callbackfn, final Object thisArg) {
+ public static boolean every(final Object self, final Object callbackfn, final Object thisArg) {
return applyEvery(Global.toObject(self), callbackfn, thisArg);
}
@@ -1254,7 +1272,7 @@ public final class NativeArray extends ScriptObject {
* @return true if callback function returned true for any element in the array, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object some(final Object self, final Object callbackfn, final Object thisArg) {
+ public static boolean some(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) {
private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER();
@@ -1295,7 +1313,7 @@ public final class NativeArray extends ScriptObject {
* @return array with elements transformed by map function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object map(final Object self, final Object callbackfn, final Object thisArg) {
+ public static NativeArray map(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) {
private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER();
@@ -1324,7 +1342,7 @@ public final class NativeArray extends ScriptObject {
* @return filtered array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object filter(final Object self, final Object callbackfn, final Object thisArg) {
+ public static NativeArray filter(final Object self, final Object callbackfn, final Object thisArg) {
return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) {
private long to = 0;
private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER();
diff --git a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index d75a2129..70c97daf 100644
--- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.objects;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -43,12 +44,8 @@ final class NativeArrayBuffer extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
+ public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
if (args.length == 0) {
throw new RuntimeException("missing length argument");
}
@@ -57,7 +54,7 @@ final class NativeArrayBuffer extends ScriptObject {
}
protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
- super(global.getArrayBufferPrototype(), global.getArrayBufferMap());
+ super(global.getArrayBufferPrototype(), $nasgenmap$);
this.buffer = byteArray;
}
@@ -84,7 +81,7 @@ final class NativeArrayBuffer extends ScriptObject {
}
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object slice(final Object self, final Object begin0, final Object end0) {
+ public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
int begin = JSType.toInt32(begin0);
int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
@@ -128,4 +125,16 @@ final class NativeArrayBuffer extends ScriptObject {
public int getByteLength() {
return buffer.length;
}
+
+ ByteBuffer getBuffer() {
+ return ByteBuffer.wrap(buffer);
+ }
+
+ ByteBuffer getBuffer(final int offset) {
+ return ByteBuffer.wrap(buffer, offset, buffer.length - offset);
+ }
+
+ ByteBuffer getBuffer(final int offset, final int length) {
+ return ByteBuffer.wrap(buffer, offset, length);
+ }
}
diff --git a/src/jdk/nashorn/internal/objects/NativeBoolean.java b/src/jdk/nashorn/internal/objects/NativeBoolean.java
index bb57cc71..d645d6dd 100644
--- a/src/jdk/nashorn/internal/objects/NativeBoolean.java
+++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java
@@ -30,6 +30,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -50,22 +51,21 @@ import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
public final class NativeBoolean extends ScriptObject {
private final boolean value;
- final static MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive boolean
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeBoolean.class, Object.class));
+ // Method handle to retrieve the Boolean prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeBoolean(final boolean value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
}
NativeBoolean(final boolean flag, final Global global) {
- this(flag, global.getBooleanPrototype(), global.getBooleanMap());
+ this(flag, global.getBooleanPrototype(), $nasgenmap$);
}
NativeBoolean(final boolean flag) {
@@ -110,7 +110,7 @@ public final class NativeBoolean extends ScriptObject {
* @return string representation of this boolean
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return getBoolean(self).toString();
}
@@ -121,7 +121,7 @@ public final class NativeBoolean extends ScriptObject {
* @return value of this boolean
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static boolean valueOf(final Object self) {
return getBoolean(self);
}
@@ -164,7 +164,7 @@ public final class NativeBoolean extends ScriptObject {
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
- return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, Boolean.class, new NativeBoolean((Boolean)receiver), WRAPFILTER, PROTOFILTER);
}
/**
@@ -178,7 +178,12 @@ public final class NativeBoolean extends ScriptObject {
return new NativeBoolean((Boolean)receiver);
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, "wrapFilter", MH.type(NativeBoolean.class, Object.class));
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getBooleanPrototype();
+ }
+
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeBoolean.class, name, type);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeDataView.java b/src/jdk/nashorn/internal/objects/NativeDataView.java
new file mode 100644
index 00000000..414ff8ae
--- /dev/null
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.objects;
+
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import jdk.nashorn.internal.objects.annotations.Attribute;
+import jdk.nashorn.internal.objects.annotations.Constructor;
+import jdk.nashorn.internal.objects.annotations.Function;
+import jdk.nashorn.internal.objects.annotations.Property;
+import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * <p>
+ * DataView builtin constructor. Based on the specification here:
+ * http://www.khronos.org/registry/typedarray/specs/latest/#8
+ * </p>
+ * <p>
+ * An ArrayBuffer is a useful object for representing an arbitrary chunk of data.
+ * In many cases, such data will be read from disk or from the network, and will
+ * not follow the alignment restrictions that are imposed on the typed array views
+ * described earlier. In addition, the data will often be heterogeneous in nature
+ * and have a defined byte order. The DataView view provides a low-level interface
+ * for reading such data from and writing it to an ArrayBuffer.
+ * </p>
+ * <p>
+ * Regardless of the host computer's endianness, DataView reads or writes values
+ * to or from main memory with a specified endianness: big or little.
+ * </p>
+ */
+@ScriptClass("DataView")
+public class NativeDataView extends ScriptObject {
+ // initialized by nasgen
+ private static PropertyMap $nasgenmap$;
+
+ // inherited ArrayBufferView properties
+
+ /**
+ * Underlying ArrayBuffer storage object
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final Object buffer;
+
+ /**
+ * The offset in bytes from the start of the ArrayBuffer
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final int byteOffset;
+
+ /**
+ * The number of bytes from the offset that this DataView will reference
+ */
+ @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
+ public final int byteLength;
+
+ // underlying ByteBuffer
+ private final ByteBuffer buf;
+
+ private NativeDataView(NativeArrayBuffer arrBuf) {
+ this(arrBuf, arrBuf.getBuffer(), 0);
+ }
+
+ private NativeDataView(NativeArrayBuffer arrBuf, int offset) {
+ this(arrBuf, bufferFrom(arrBuf, offset), offset);
+ }
+
+ private NativeDataView(NativeArrayBuffer arrBuf, int offset, int length) {
+ this(arrBuf, bufferFrom(arrBuf, offset, length), offset, length);
+ }
+
+ private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset) {
+ this(arrBuf, buf, offset, buf.capacity() - offset);
+ }
+
+ private NativeDataView(final NativeArrayBuffer arrBuf, final ByteBuffer buf, final int offset, final int length) {
+ super(Global.instance().getDataViewPrototype(), $nasgenmap$);
+ this.buffer = arrBuf;
+ this.byteOffset = offset;
+ this.byteLength = length;
+ this.buf = buf;
+ }
+
+ /**
+ * Create a new DataView object using the passed ArrayBuffer for its
+ * storage. Optional byteOffset and byteLength can be used to limit the
+ * section of the buffer referenced. The byteOffset indicates the offset in
+ * bytes from the start of the ArrayBuffer, and the byteLength is the number
+ * of bytes from the offset that this DataView will reference. If both
+ * byteOffset and byteLength are omitted, the DataView spans the entire
+ * ArrayBuffer range. If the byteLength is omitted, the DataView extends from
+ * the given byteOffset until the end of the ArrayBuffer.
+ *
+ * If the given byteOffset and byteLength references an area beyond the end
+ * of the ArrayBuffer an exception is raised.
+
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param args arguments to the constructor
+ * @return newly constructed DataView object
+ */
+ @Constructor(arity = 1)
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object... args) {
+ if (args.length == 0 || !(args[0] instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+
+ final NativeArrayBuffer arrBuf = (NativeArrayBuffer) args[0];
+ switch (args.length) {
+ case 1:
+ return new NativeDataView(arrBuf);
+ case 2:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]));
+ default:
+ return new NativeDataView(arrBuf, JSType.toInt32(args[1]), JSType.toInt32(args[2]));
+ }
+ }
+
+ /**
+ * Specialized version of DataView constructor
+ *
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param arrBuf underlying ArrayBuffer storage object
+ * @param offset offset in bytes from the start of the ArrayBuffer
+ * @return newly constructed DataView object
+ */
+ @SpecializedConstructor
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset) {
+ if (!(arrBuf instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+ return new NativeDataView((NativeArrayBuffer) arrBuf, offset);
+ }
+
+ /**
+ * Specialized version of DataView constructor
+ *
+ * @param newObj if this constructor was invoked with 'new' or not
+ * @param self constructor function object
+ * @param arrBuf underlying ArrayBuffer storage object
+ * @param offset in bytes from the start of the ArrayBuffer
+ * @param length is the number of bytes from the offset that this DataView will reference
+ * @return newly constructed DataView object
+ */
+ @SpecializedConstructor
+ public static NativeDataView constructor(final boolean newObj, final Object self, final Object arrBuf, final int offset, final int length) {
+ if (!(arrBuf instanceof NativeArrayBuffer)) {
+ throw typeError("not.an.arraybuffer.in.dataview");
+ }
+ return new NativeDataView((NativeArrayBuffer) arrBuf, offset, length);
+ }
+
+ // Gets the value of the given type at the specified byte offset
+ // from the start of the view. There is no alignment constraint;
+ // multi-byte values may be fetched from any offset.
+ //
+ // For multi-byte values, the optional littleEndian argument
+ // indicates whether a big-endian or little-endian value should be
+ // read. If false or undefined, a big-endian value is read.
+ //
+ // These methods raise an exception if they would read
+ // beyond the end of the view.
+
+ /**
+ * Get 8-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static int getInt8(final Object self, final Object byteOffset) {
+ try {
+ return getBuffer(self).get(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt8(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self).get(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE)
+ public static int getUint8(final Object self, final Object byteOffset) {
+ try {
+ return (0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 8-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 8-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint8(final Object self, final int byteOffset) {
+ try {
+ return (0xFF & getBuffer(self).get(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt16(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getShort(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getShort(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint16(final Object self, final int byteOffset) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, false).getShort(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 16-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 16-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt32(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getInt(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit signed int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit signed int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getInt(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static long getUint32(final Object self, final int byteOffset) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit unsigned int from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit unsigned int value at the byteOffset
+ */
+ @SpecializedFunction
+ public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit float value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 32-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat32(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getFloat(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 32-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 32-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getFloat(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 64-bit float value at the byteOffset
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
+ public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset));
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @return 64-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat64(final Object self, final int byteOffset) {
+ try {
+ return getBuffer(self, false).getDouble(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Get 64-bit float value from given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param littleEndian (optional) flag indicating whether to read in little endian order
+ * @return 64-bit float value at the byteOffset
+ */
+ @SpecializedFunction
+ public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) {
+ try {
+ return getBuffer(self, littleEndian).getDouble(byteOffset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ // Stores a value of the given type at the specified byte offset
+ // from the start of the view. There is no alignment constraint;
+ // multi-byte values may be stored at any offset.
+ //
+ // For multi-byte values, the optional littleEndian argument
+ // indicates whether the value should be stored in big-endian or
+ // little-endian byte order. If false or undefined, the value is
+ // stored in big-endian byte order.
+ //
+ // These methods raise an exception if they would write
+ // beyond the end of the view.
+
+ /**
+ * Set 8-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param value byte value to set
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt8(final Object self, final Object byteOffset, final Object value) {
+ try {
+ getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to read from
+ * @param value byte value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt8(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self).put(byteOffset, (byte)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value byte value to set
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint8(final Object self, final Object byteOffset, final Object value) {
+ try {
+ getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 8-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value byte value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint8(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self).put(byteOffset, (byte)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt16(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt16(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint16(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint16(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 16-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value short value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint16(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toInt32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt32(final Object self, final int byteOffset, final int value) {
+ try {
+ getBuffer(self, false).putInt(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit signed int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setInt32(final Object self, final int byteOffset, final int value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setUint32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint32(final Object self, final int byteOffset, final long value) {
+ try {
+ getBuffer(self, false).putInt(byteOffset, (int)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit unsigned int at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value int value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setUint32(final Object self, final int byteOffset, final long value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putInt(byteOffset, (int)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setFloat32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat32(final Object self, final int byteOffset, final double value) {
+ try {
+ getBuffer(self, false).putFloat(byteOffset, (float)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 32-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value float value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat32(final Object self, final int byteOffset, final double value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putFloat(byteOffset, (float)value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
+ public static Object setFloat64(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value));
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat64(final Object self, final int byteOffset, final double value) {
+ try {
+ getBuffer(self, false).putDouble(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ /**
+ * Set 64-bit float at the given byteOffset
+ *
+ * @param self DataView object
+ * @param byteOffset byte offset to write at
+ * @param value double value to set
+ * @param littleEndian (optional) flag indicating whether to write in little endian order
+ * @return undefined
+ */
+ @SpecializedFunction
+ public static Object setFloat64(final Object self, final int byteOffset, final double value, final boolean littleEndian) {
+ try {
+ getBuffer(self, littleEndian).putDouble(byteOffset, value);
+ return UNDEFINED;
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.offset");
+ }
+ }
+
+ // internals only below this point
+ private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) {
+ try {
+ return nab.getBuffer(offset);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.constructor.offset");
+ }
+ }
+
+ private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) {
+ try {
+ return nab.getBuffer(offset, length);
+ } catch (final IndexOutOfBoundsException ioe) {
+ throw rangeError(ioe, "dataview.constructor.offset");
+ }
+ }
+
+ private static NativeDataView checkSelf(final Object self) {
+ if (!(self instanceof NativeDataView)) {
+ throw typeError("not.an.arraybuffer", ScriptRuntime.safeToString(self));
+ }
+ return (NativeDataView)self;
+ }
+
+ private static ByteBuffer getBuffer(final Object self) {
+ return checkSelf(self).buf;
+ }
+
+ private static ByteBuffer getBuffer(final Object self, final Object littleEndian) {
+ return getBuffer(self, JSType.toBoolean(littleEndian));
+ }
+
+ private static ByteBuffer getBuffer(final Object self, final boolean littleEndian) {
+ return getBuffer(self).order(littleEndian? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+ }
+}
diff --git a/src/jdk/nashorn/internal/objects/NativeDate.java b/src/jdk/nashorn/internal/objects/NativeDate.java
index 935285f0..b3661df7 100644
--- a/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -114,10 +114,6 @@ public final class NativeDate extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeDate(final double time, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
final ScriptEnvironment env = Global.getEnv();
@@ -127,7 +123,7 @@ public final class NativeDate extends ScriptObject {
}
NativeDate(final double time, final Global global) {
- this(time, global.getDatePrototype(), global.getDateMap());
+ this(time, global.getDatePrototype(), $nasgenmap$);
}
private NativeDate (final double time) {
@@ -230,7 +226,7 @@ public final class NativeDate extends ScriptObject {
* @return Date interpreted from the string, or NaN for illegal values
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object parse(final Object self, final Object string) {
+ public static double parse(final Object self, final Object string) {
return parseDateString(JSType.toString(string));
}
@@ -242,7 +238,7 @@ public final class NativeDate extends ScriptObject {
* @return a time clip according to the ECMA specification
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 7, where = Where.CONSTRUCTOR)
- public static Object UTC(final Object self, final Object... args) {
+ public static double UTC(final Object self, final Object... args) {
final NativeDate nd = new NativeDate(0);
final double[] d = convertCtorArgs(args);
final double time = d == null ? Double.NaN : timeClip(makeDate(d));
@@ -257,8 +253,8 @@ public final class NativeDate extends ScriptObject {
* @return a Date that points to the current moment in time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object now(final Object self) {
- return (double)System.currentTimeMillis();
+ public static long now(final Object self) {
+ return System.currentTimeMillis();
}
/**
@@ -268,7 +264,7 @@ public final class NativeDate extends ScriptObject {
* @return string value that represents the Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return toStringImpl(self, FORMAT_DATE_TIME);
}
@@ -279,7 +275,7 @@ public final class NativeDate extends ScriptObject {
* @return string value with the "date" part of the Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toDateString(final Object self) {
+ public static String toDateString(final Object self) {
return toStringImpl(self, FORMAT_DATE);
}
@@ -290,7 +286,7 @@ public final class NativeDate extends ScriptObject {
* @return string value with "time" part of Date in the current time zone
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toTimeString(final Object self) {
+ public static String toTimeString(final Object self) {
return toStringImpl(self, FORMAT_TIME);
}
@@ -301,7 +297,7 @@ public final class NativeDate extends ScriptObject {
* @return string value that represents the Data in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_DATE_TIME);
}
@@ -312,7 +308,7 @@ public final class NativeDate extends ScriptObject {
* @return string value with the "date" part of the Date in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleDateString(final Object self) {
+ public static String toLocaleDateString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_DATE);
}
@@ -323,7 +319,7 @@ public final class NativeDate extends ScriptObject {
* @return string value with the "time" part of Date in the current time zone and locale
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleTimeString(final Object self) {
+ public static String toLocaleTimeString(final Object self) {
return toStringImpl(self, FORMAT_LOCAL_TIME);
}
@@ -334,7 +330,7 @@ public final class NativeDate extends ScriptObject {
* @return valueOf - a number which is this time value
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static double valueOf(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null) ? nd.getTime() : Double.NaN;
}
@@ -346,7 +342,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getTime(final Object self) {
+ public static double getTime(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null) ? nd.getTime() : Double.NaN;
}
@@ -369,7 +365,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC full year
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCFullYear(final Object self) {
+ public static double getUTCFullYear(final Object self) {
return getUTCField(self, YEAR);
}
@@ -380,7 +376,7 @@ public final class NativeDate extends ScriptObject {
* @return year
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getYear(final Object self) {
+ public static double getYear(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? (yearFromTime(nd.getLocalTime()) - 1900) : Double.NaN;
}
@@ -392,7 +388,7 @@ public final class NativeDate extends ScriptObject {
* @return month
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMonth(final Object self) {
+ public static double getMonth(final Object self) {
return getField(self, MONTH);
}
@@ -403,7 +399,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC month
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMonth(final Object self) {
+ public static double getUTCMonth(final Object self) {
return getUTCField(self, MONTH);
}
@@ -414,7 +410,7 @@ public final class NativeDate extends ScriptObject {
* @return date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getDate(final Object self) {
+ public static double getDate(final Object self) {
return getField(self, DAY);
}
@@ -425,7 +421,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC Date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCDate(final Object self) {
+ public static double getUTCDate(final Object self) {
return getUTCField(self, DAY);
}
@@ -436,7 +432,7 @@ public final class NativeDate extends ScriptObject {
* @return day
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getDay(final Object self) {
+ public static double getDay(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? weekDay(nd.getLocalTime()) : Double.NaN;
}
@@ -448,7 +444,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC day
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCDay(final Object self) {
+ public static double getUTCDay(final Object self) {
final NativeDate nd = getNativeDate(self);
return (nd != null && nd.isValidDate()) ? weekDay(nd.getTime()) : Double.NaN;
}
@@ -460,7 +456,7 @@ public final class NativeDate extends ScriptObject {
* @return hours
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getHours(final Object self) {
+ public static double getHours(final Object self) {
return getField(self, HOUR);
}
@@ -471,7 +467,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC hours
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCHours(final Object self) {
+ public static double getUTCHours(final Object self) {
return getUTCField(self, HOUR);
}
@@ -482,7 +478,7 @@ public final class NativeDate extends ScriptObject {
* @return minutes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMinutes(final Object self) {
+ public static double getMinutes(final Object self) {
return getField(self, MINUTE);
}
@@ -493,7 +489,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC minutes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMinutes(final Object self) {
+ public static double getUTCMinutes(final Object self) {
return getUTCField(self, MINUTE);
}
@@ -504,7 +500,7 @@ public final class NativeDate extends ScriptObject {
* @return seconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getSeconds(final Object self) {
+ public static double getSeconds(final Object self) {
return getField(self, SECOND);
}
@@ -515,7 +511,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC seconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCSeconds(final Object self) {
+ public static double getUTCSeconds(final Object self) {
return getUTCField(self, SECOND);
}
@@ -526,7 +522,7 @@ public final class NativeDate extends ScriptObject {
* @return milliseconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getMilliseconds(final Object self) {
+ public static double getMilliseconds(final Object self) {
return getField(self, MILLISECOND);
}
@@ -537,7 +533,7 @@ public final class NativeDate extends ScriptObject {
* @return UTC milliseconds
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getUTCMilliseconds(final Object self) {
+ public static double getUTCMilliseconds(final Object self) {
return getUTCField(self, MILLISECOND);
}
@@ -548,7 +544,7 @@ public final class NativeDate extends ScriptObject {
* @return time zone offset or NaN if N/A
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getTimezoneOffset(final Object self) {
+ public static double getTimezoneOffset(final Object self) {
final NativeDate nd = getNativeDate(self);
if (nd != null && nd.isValidDate()) {
final long msec = (long) nd.getTime();
@@ -565,7 +561,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object setTime(final Object self, final Object time) {
+ public static double setTime(final Object self, final Object time) {
final NativeDate nd = getNativeDate(self);
final double num = timeClip(JSType.toNumber(time));
nd.setTime(num);
@@ -580,7 +576,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setMilliseconds(final Object self, final Object... args) {
+ public static double setMilliseconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MILLISECOND, args, true);
return nd.getTime();
@@ -594,7 +590,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setUTCMilliseconds(final Object self, final Object... args) {
+ public static double setUTCMilliseconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MILLISECOND, args, false);
return nd.getTime();
@@ -608,7 +604,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setSeconds(final Object self, final Object... args) {
+ public static double setSeconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, SECOND, args, true);
return nd.getTime();
@@ -622,7 +618,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setUTCSeconds(final Object self, final Object... args) {
+ public static double setUTCSeconds(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, SECOND, args, false);
return nd.getTime();
@@ -636,7 +632,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setMinutes(final Object self, final Object... args) {
+ public static double setMinutes(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MINUTE, args, true);
return nd.getTime();
@@ -650,7 +646,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setUTCMinutes(final Object self, final Object... args) {
+ public static double setUTCMinutes(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MINUTE, args, false);
return nd.getTime();
@@ -664,7 +660,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static Object setHours(final Object self, final Object... args) {
+ public static double setHours(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, HOUR, args, true);
return nd.getTime();
@@ -678,7 +674,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static Object setUTCHours(final Object self, final Object... args) {
+ public static double setUTCHours(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, HOUR, args, false);
return nd.getTime();
@@ -692,7 +688,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setDate(final Object self, final Object... args) {
+ public static double setDate(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, DAY, args, true);
return nd.getTime();
@@ -706,7 +702,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object setUTCDate(final Object self, final Object... args) {
+ public static double setUTCDate(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, DAY, args, false);
return nd.getTime();
@@ -720,7 +716,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setMonth(final Object self, final Object... args) {
+ public static double setMonth(final Object self, final Object... args) {
final NativeDate nd = getNativeDate(self);
setFields(nd, MONTH, args, true);
return nd.getTime();
@@ -734,7 +730,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static Object setUTCMonth(final Object self, final Object... args) {
+ public static double setUTCMonth(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
setFields(nd, MONTH, args, false);
return nd.getTime();
@@ -748,7 +744,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setFullYear(final Object self, final Object... args) {
+ public static double setFullYear(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
if (nd.isValidDate()) {
setFields(nd, YEAR, args, true);
@@ -771,7 +767,7 @@ public final class NativeDate extends ScriptObject {
* @return time
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static Object setUTCFullYear(final Object self, final Object... args) {
+ public static double setUTCFullYear(final Object self, final Object... args) {
final NativeDate nd = ensureNativeDate(self);
if (nd.isValidDate()) {
setFields(nd, YEAR, args, false);
@@ -790,7 +786,7 @@ public final class NativeDate extends ScriptObject {
* @return NativeDate
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object setYear(final Object self, final Object year) {
+ public static double setYear(final Object self, final Object year) {
final NativeDate nd = getNativeDate(self);
if (isNaN(nd.getTime())) {
nd.setTime(utc(0, nd.getTimeZone()));
@@ -817,7 +813,7 @@ public final class NativeDate extends ScriptObject {
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toUTCString(final Object self) {
+ public static String toUTCString(final Object self) {
return toGMTStringImpl(self);
}
@@ -830,7 +826,7 @@ public final class NativeDate extends ScriptObject {
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toGMTString(final Object self) {
+ public static String toGMTString(final Object self) {
return toGMTStringImpl(self);
}
@@ -841,7 +837,7 @@ public final class NativeDate extends ScriptObject {
* @return string representation of date
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toISOString(final Object self) {
+ public static String toISOString(final Object self) {
return toISOStringImpl(self);
}
@@ -1286,14 +1282,14 @@ public final class NativeDate extends ScriptObject {
}
}
- private static Object getField(final Object self, final int field) {
+ private static double getField(final Object self, final int field) {
final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getLocalTime()) : Double.NaN;
+ return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getLocalTime()) : Double.NaN;
}
- private static Object getUTCField(final Object self, final int field) {
+ private static double getUTCField(final Object self, final int field) {
final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? valueFromTime(field, nd.getTime()) : Double.NaN;
+ return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getTime()) : Double.NaN;
}
private static void setFields(final NativeDate nd, final int fieldId, final Object[] args, final boolean local) {
@@ -1348,5 +1344,4 @@ public final class NativeDate extends ScriptObject {
private TimeZone getTimeZone() {
return timezone;
}
-
}
diff --git a/src/jdk/nashorn/internal/objects/NativeDebug.java b/src/jdk/nashorn/internal/objects/NativeDebug.java
index 9ee7c99a..5d80c37b 100644
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -34,7 +34,7 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.PropertyListenerManager;
+import jdk.nashorn.internal.runtime.PropertyListeners;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -116,7 +116,7 @@ public final class NativeDebug extends ScriptObject {
* @return true if reference identity
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object identical(final Object self, final Object obj1, final Object obj2) {
+ public static boolean identical(final Object self, final Object obj1, final Object obj2) {
return obj1 == obj2;
}
@@ -144,7 +144,7 @@ public final class NativeDebug extends ScriptObject {
* @return return {@link Object#equals(Object)} for objects.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object equals(final Object self, final Object obj1, final Object obj2) {
+ public static boolean equals(final Object self, final Object obj1, final Object obj2) {
return Objects.equals(obj1, obj2);
}
@@ -156,7 +156,7 @@ public final class NativeDebug extends ScriptObject {
* @return Java string representation of {@code obj}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toJavaString(final Object self, final Object obj) {
+ public static String toJavaString(final Object self, final Object obj) {
return Objects.toString(obj);
}
@@ -168,7 +168,7 @@ public final class NativeDebug extends ScriptObject {
* @return string representation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object toIdentString(final Object self, final Object obj) {
+ public static String toIdentString(final Object self, final Object obj) {
if (obj == null) {
return "null";
}
@@ -185,8 +185,8 @@ public final class NativeDebug extends ScriptObject {
* @return listener count
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object getListenerCount(final Object self, final Object obj) {
- return (obj instanceof ScriptObject)? ((ScriptObject)obj).getListenerCount() : 0;
+ public static int getListenerCount(final Object self, final Object obj) {
+ return (obj instanceof ScriptObject) ? PropertyListeners.getListenerCount((ScriptObject) obj) : 0;
}
/**
@@ -203,14 +203,13 @@ public final class NativeDebug extends ScriptObject {
out.println("ScriptObject count " + ScriptObject.getCount());
out.println("Scope count " + ScriptObject.getScopeCount());
- out.println("ScriptObject listeners added " + PropertyListenerManager.getListenersAdded());
- out.println("ScriptObject listeners removed " + PropertyListenerManager.getListenersRemoved());
+ out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded());
+ out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved());
out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
out.println("ScriptFunction invokes " + ScriptFunction.getInvokes());
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
out.println("PropertyMap count " + PropertyMap.getCount());
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
- out.println("PropertyMap shared " + PropertyMap.getSharedCount());
out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
diff --git a/src/jdk/nashorn/internal/objects/NativeError.java b/src/jdk/nashorn/internal/objects/NativeError.java
index d3e2effe..1b6b8094 100644
--- a/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeError.java
@@ -38,7 +38,6 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -75,7 +74,7 @@ public final class NativeError extends ScriptObject {
static final String FILENAME = "__fileName__";
/** Message property name */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** ECMA 15.11.4.2 Error.prototype.name */
@@ -86,13 +85,14 @@ public final class NativeError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -100,10 +100,11 @@ public final class NativeError extends ScriptObject {
} else {
this.delete(NativeError.MESSAGE, false);
}
+ initException(this);
}
NativeError(final Object msg, final Global global) {
- this(msg, global.getErrorPrototype(), global.getErrorMap());
+ this(msg, global.getErrorPrototype(), $nasgenmap$);
}
private NativeError(final Object msg) {
@@ -125,10 +126,18 @@ public final class NativeError extends ScriptObject {
* @return NativeError instance
*/
@Constructor
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeError(msg);
}
+ // This is called NativeError, NativeTypeError etc. to
+ // associate a ECMAException with the ECMA Error object.
+ @SuppressWarnings("unused")
+ static void initException(final ScriptObject self) {
+ // ECMAException constructor has side effects
+ new ECMAException(self, null);
+ }
+
/**
* Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided.
*
@@ -136,16 +145,17 @@ public final class NativeError extends ScriptObject {
* @param errorObj the error object
* @return undefined
*/
- @SuppressWarnings("unused")
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object captureStackTrace(final Object self, final Object errorObj) {
Global.checkObject(errorObj);
final ScriptObject sobj = (ScriptObject)errorObj;
- new ECMAException(sobj, null); //constructor has side effects
- sobj.delete("stack", false);
- final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
- final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
- sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
+ initException(sobj);
+ sobj.delete(STACK, false);
+ if (! sobj.has("stack")) {
+ final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
+ final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
+ sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
+ }
return UNDEFINED;
}
@@ -226,7 +236,11 @@ public final class NativeError extends ScriptObject {
public static Object setLineNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(LINENUMBER, value, false);
+ if (sobj.hasOwnProperty(LINENUMBER)) {
+ sobj.put(LINENUMBER, value, false);
+ } else {
+ sobj.addOwnProperty(LINENUMBER, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -254,7 +268,11 @@ public final class NativeError extends ScriptObject {
public static Object setColumnNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(COLUMNNUMBER, value, false);
+ if (sobj.hasOwnProperty(COLUMNNUMBER)) {
+ sobj.put(COLUMNNUMBER, value, false);
+ } else {
+ sobj.addOwnProperty(COLUMNNUMBER, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -282,7 +300,11 @@ public final class NativeError extends ScriptObject {
public static Object setFileName(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(FILENAME, value, false);
+ if (sobj.hasOwnProperty(FILENAME)) {
+ sobj.put(FILENAME, value, false);
+ } else {
+ sobj.addOwnProperty(FILENAME, Attribute.NOT_ENUMERABLE, value);
+ }
return value;
}
@@ -304,10 +326,12 @@ public final class NativeError extends ScriptObject {
final Object exception = ECMAException.getException(sobj);
if (exception instanceof Throwable) {
- return getScriptStackString(sobj, (Throwable)exception);
+ Object value = getScriptStackString(sobj, (Throwable)exception);
+ sobj.put(STACK, value, false);
+ return value;
}
- return "";
+ return UNDEFINED;
}
/**
diff --git a/src/jdk/nashorn/internal/objects/NativeEvalError.java b/src/jdk/nashorn/internal/objects/NativeEvalError.java
index 89e9485f..586c7cff 100644
--- a/src/jdk/nashorn/internal/objects/NativeEvalError.java
+++ b/src/jdk/nashorn/internal/objects/NativeEvalError.java
@@ -44,7 +44,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeEvalError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@ public final class NativeEvalError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeEvalError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@ public final class NativeEvalError extends ScriptObject {
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeEvalError(final Object msg, final Global global) {
- this(msg, global.getEvalErrorPrototype(), global.getEvalErrorMap());
+ this(msg, global.getEvalErrorPrototype(), $nasgenmap$);
}
private NativeEvalError(final Object msg) {
@@ -96,7 +98,7 @@ public final class NativeEvalError extends ScriptObject {
* @return new EvalError
*/
@Constructor(name = "EvalError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeEvalError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeEvalError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index b96c81c9..a9dfb7a4 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -136,8 +136,8 @@ public final class NativeFloat32Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeFloat32Array)constructorImpl(args, FACTORY);
}
NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -192,8 +192,8 @@ public final class NativeFloat32Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeFloat32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeFloat32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index af9251f4..61b58807 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -146,8 +146,8 @@ public final class NativeFloat64Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeFloat64Array)constructorImpl(args, FACTORY);
}
NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -202,8 +202,8 @@ public final class NativeFloat64Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeFloat64Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeFloat64Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java
index d092cfb6..013683e0 100644
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -27,6 +27,7 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.util.List;
@@ -71,7 +72,7 @@ public final class NativeFunction {
* @return string representation of Function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -174,7 +175,7 @@ public final class NativeFunction {
* @return function with bound arguments
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object bind(final Object self, final Object... args) {
+ public static ScriptFunction bind(final Object self, final Object... args) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -199,7 +200,7 @@ public final class NativeFunction {
* @return source for function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toSource(final Object self) {
+ public static String toSource(final Object self) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function", ScriptRuntime.safeToString(self));
}
@@ -217,7 +218,7 @@ public final class NativeFunction {
* @return new NativeFunction
*/
@Constructor(arity = 1)
- public static Object function(final boolean newObj, final Object self, final Object... args) {
+ public static ScriptFunction function(final boolean newObj, final Object self, final Object... args) {
final StringBuilder sb = new StringBuilder();
sb.append("(function (");
@@ -253,11 +254,11 @@ public final class NativeFunction {
final Global global = Global.instance();
- return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
+ return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
}
private static void checkFunctionParameters(final String params) {
- final Source src = new Source("<function>", params);
+ final Source src = sourceFor("<function>", params);
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
try {
parser.parseFormalParameterList();
@@ -267,7 +268,7 @@ public final class NativeFunction {
}
private static void checkFunctionBody(final String funcBody) {
- final Source src = new Source("<function>", funcBody);
+ final Source src = sourceFor("<function>", funcBody);
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
try {
parser.parseFunctionBody();
diff --git a/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index e24691af..f6aa2054 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -100,8 +100,8 @@ public final class NativeInt16Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt16Array)constructorImpl(args, FACTORY);
}
NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -151,8 +151,8 @@ public final class NativeInt16Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt16Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index b25f8495..643bd816 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -103,8 +103,8 @@ public final class NativeInt32Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt32Array)constructorImpl(args, FACTORY);
}
NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -154,8 +154,8 @@ public final class NativeInt32Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index e5069107..5822c6d5 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -93,8 +93,8 @@ public final class NativeInt8Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeInt8Array)constructorImpl(args, FACTORY);
}
NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -144,8 +144,8 @@ public final class NativeInt8Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeInt8Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeInt8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index 668ca8cd..84036a32 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -146,10 +146,6 @@ public final class NativeJSAdapter extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
NativeJSAdapter(final Object overrides, final ScriptObject adaptee, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.adaptee = wrapAdaptee(adaptee);
@@ -163,7 +159,7 @@ public final class NativeJSAdapter extends ScriptObject {
}
private static ScriptObject wrapAdaptee(final ScriptObject adaptee) {
- return new JO(adaptee, Global.instance().getObjectMap());
+ return new JO(adaptee, JO.getInitialMap());
}
@Override
@@ -540,7 +536,7 @@ public final class NativeJSAdapter extends ScriptObject {
* @return new NativeJSAdapter
*/
@Constructor
- public static Object construct(final boolean isNew, final Object self, final Object... args) {
+ public static NativeJSAdapter construct(final boolean isNew, final Object self, final Object... args) {
Object proto = UNDEFINED;
Object overrides = UNDEFINED;
Object adaptee;
@@ -577,7 +573,7 @@ public final class NativeJSAdapter extends ScriptObject {
proto = global.getJSAdapterPrototype();
}
- return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, global.getJSAdapterMap());
+ return new NativeJSAdapter(overrides, (ScriptObject)adaptee, (ScriptObject)proto, $nasgenmap$);
}
@Override
@@ -622,14 +618,14 @@ public final class NativeJSAdapter extends ScriptObject {
case "getMethod":
final FindProperty find = adaptee.findProperty(__call__, true);
if (find != null) {
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (value instanceof ScriptFunction) {
final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
// TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
- adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__),
+ adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
testJSAdaptor(adaptee, null, null, null));
}
}
@@ -691,7 +687,7 @@ public final class NativeJSAdapter extends ScriptObject {
final MethodType type = desc.getMethodType();
if (findData != null) {
final String name = desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null;
- final Object value = getObjectValue(findData);
+ final Object value = findData.getObjectValue();
if (value instanceof ScriptFunction) {
final ScriptFunction func = (ScriptFunction)value;
@@ -700,7 +696,7 @@ public final class NativeJSAdapter extends ScriptObject {
if (methodHandle != null) {
return new GuardedInvocation(
methodHandle,
- adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
+ adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
}
}
@@ -713,7 +709,7 @@ public final class NativeJSAdapter extends ScriptObject {
final MethodHandle methodHandle = hook.equals(__put__) ?
MH.asType(Lookup.EMPTY_SETTER, type) :
Lookup.emptyGetter(type.returnType());
- return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null));
+ return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJava.java b/src/jdk/nashorn/internal/objects/NativeJava.java
index b863e24f..7879bab4 100644
--- a/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -75,7 +75,7 @@ public final class NativeJava {
* @see #type(Object, Object)
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isType(final Object self, final Object type) {
+ public static boolean isType(final Object self, final Object type) {
return type instanceof StaticClass;
}
@@ -338,7 +338,7 @@ public final class NativeJava {
* null.
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object from(final Object self, final Object objArray) {
+ public static NativeArray from(final Object self, final Object objArray) {
if (objArray == null) {
return null;
} else if (objArray instanceof Collection) {
diff --git a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 3e46a2c7..40ecbffc 100644
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -60,17 +60,13 @@ public final class NativeJavaImporter extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeJavaImporter(final Object[] args, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.args = args;
}
private NativeJavaImporter(final Object[] args, final Global global) {
- this(args, global.getJavaImporterPrototype(), global.getJavaImporterMap());
+ this(args, global.getJavaImporterPrototype(), $nasgenmap$);
}
private NativeJavaImporter(final Object[] args) {
@@ -90,7 +86,7 @@ public final class NativeJavaImporter extends ScriptObject {
* @return NativeJavaImporter instance
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+ public static NativeJavaImporter constructor(final boolean isNew, final Object self, final Object... args) {
return new NativeJavaImporter(args);
}
@@ -134,6 +130,11 @@ public final class NativeJavaImporter extends ScriptObject {
return createAndSetProperty(desc) ? super.lookup(desc, request) : super.noSuchMethod(desc, request);
}
+ @Override
+ protected Object invokeNoSuchProperty(final String name) {
+ return createProperty(name);
+ }
+
private boolean createAndSetProperty(final CallSiteDescriptor desc) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Object value = createProperty(name);
diff --git a/src/jdk/nashorn/internal/objects/NativeMath.java b/src/jdk/nashorn/internal/objects/NativeMath.java
index cc50fbb4..ec53965a 100644
--- a/src/jdk/nashorn/internal/objects/NativeMath.java
+++ b/src/jdk/nashorn/internal/objects/NativeMath.java
@@ -92,7 +92,7 @@ public final class NativeMath extends ScriptObject {
* @return abs of value
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object abs(final Object self, final Object x) {
+ public static double abs(final Object self, final Object x) {
return Math.abs(JSType.toNumber(x));
}
@@ -144,7 +144,7 @@ public final class NativeMath extends ScriptObject {
* @return acos of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object acos(final Object self, final Object x) {
+ public static double acos(final Object self, final Object x) {
return Math.acos(JSType.toNumber(x));
}
@@ -170,7 +170,7 @@ public final class NativeMath extends ScriptObject {
* @return asin of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object asin(final Object self, final Object x) {
+ public static double asin(final Object self, final Object x) {
return Math.asin(JSType.toNumber(x));
}
@@ -196,7 +196,7 @@ public final class NativeMath extends ScriptObject {
* @return atan of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object atan(final Object self, final Object x) {
+ public static double atan(final Object self, final Object x) {
return Math.atan(JSType.toNumber(x));
}
@@ -223,7 +223,7 @@ public final class NativeMath extends ScriptObject {
* @return atan2 of x and y
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object atan2(final Object self, final Object y, final Object x) {
+ public static double atan2(final Object self, final Object y, final Object x) {
return Math.atan2(JSType.toNumber(y), JSType.toNumber(x));
}
@@ -250,7 +250,7 @@ public final class NativeMath extends ScriptObject {
* @return ceil of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object ceil(final Object self, final Object x) {
+ public static double ceil(final Object self, final Object x) {
return Math.ceil(JSType.toNumber(x));
}
@@ -302,7 +302,7 @@ public final class NativeMath extends ScriptObject {
* @return cos of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object cos(final Object self, final Object x) {
+ public static double cos(final Object self, final Object x) {
return Math.cos(JSType.toNumber(x));
}
@@ -328,7 +328,7 @@ public final class NativeMath extends ScriptObject {
* @return exp of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object exp(final Object self, final Object x) {
+ public static double exp(final Object self, final Object x) {
return Math.exp(JSType.toNumber(x));
}
@@ -341,7 +341,7 @@ public final class NativeMath extends ScriptObject {
* @return floor of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object floor(final Object self, final Object x) {
+ public static double floor(final Object self, final Object x) {
return Math.floor(JSType.toNumber(x));
}
@@ -393,7 +393,7 @@ public final class NativeMath extends ScriptObject {
* @return log of argument
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object log(final Object self, final Object x) {
+ public static double log(final Object self, final Object x) {
return Math.log(JSType.toNumber(x));
}
@@ -419,7 +419,7 @@ public final class NativeMath extends ScriptObject {
* @return the largest of the arguments, {@link Double#NEGATIVE_INFINITY} if no args given, or identity if one arg is given
*/
@Function(arity = 2, attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object max(final Object self, final Object... args) {
+ public static double max(final Object self, final Object... args) {
switch (args.length) {
case 0:
return Double.NEGATIVE_INFINITY;
@@ -497,7 +497,7 @@ public final class NativeMath extends ScriptObject {
* @return the smallest of the arguments, {@link Double#NEGATIVE_INFINITY} if no args given, or identity if one arg is given
*/
@Function(arity = 2, attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object min(final Object self, final Object... args) {
+ public static double min(final Object self, final Object... args) {
switch (args.length) {
case 0:
return Double.POSITIVE_INFINITY;
@@ -576,7 +576,7 @@ public final class NativeMath extends ScriptObject {
* @return x raised to the power of y
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object pow(final Object self, final Object x, final Object y) {
+ public static double pow(final Object self, final Object x, final Object y) {
return Math.pow(JSType.toNumber(x), JSType.toNumber(y));
}
@@ -602,7 +602,7 @@ public final class NativeMath extends ScriptObject {
* @return random number in the range [0..1)
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object random(final Object self) {
+ public static double random(final Object self) {
return Math.random();
}
@@ -615,7 +615,7 @@ public final class NativeMath extends ScriptObject {
* @return x rounded
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object round(final Object self, final Object x) {
+ public static double round(final Object self, final Object x) {
final double d = JSType.toNumber(x);
if (Math.getExponent(d) >= 52) {
return d;
@@ -632,7 +632,7 @@ public final class NativeMath extends ScriptObject {
* @return sin of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object sin(final Object self, final Object x) {
+ public static double sin(final Object self, final Object x) {
return Math.sin(JSType.toNumber(x));
}
@@ -658,7 +658,7 @@ public final class NativeMath extends ScriptObject {
* @return sqrt of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object sqrt(final Object self, final Object x) {
+ public static double sqrt(final Object self, final Object x) {
return Math.sqrt(JSType.toNumber(x));
}
@@ -684,7 +684,7 @@ public final class NativeMath extends ScriptObject {
* @return tan of x
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where=Where.CONSTRUCTOR)
- public static Object tan(final Object self, final Object x) {
+ public static double tan(final Object self, final Object x) {
return Math.tan(JSType.toNumber(x));
}
diff --git a/src/jdk/nashorn/internal/objects/NativeNumber.java b/src/jdk/nashorn/internal/objects/NativeNumber.java
index d9d568b7..a95587ef 100644
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -34,6 +34,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.text.NumberFormat;
import java.util.Locale;
import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -57,7 +58,10 @@ import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
@ScriptClass("Number")
public final class NativeNumber extends ScriptObject {
- static final MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive number
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeNumber.class, Object.class));
+ // Method handle to retrieve the Number prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
/** ECMA 15.7.3.2 largest positive finite value */
@Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT, where = Where.CONSTRUCTOR)
@@ -86,10 +90,6 @@ public final class NativeNumber extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeNumber(final double value, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
this.value = value;
@@ -98,7 +98,7 @@ public final class NativeNumber extends ScriptObject {
}
NativeNumber(final double value, final Global global) {
- this(value, global.getNumberPrototype(), global.getNumberMap());
+ this(value, global.getNumberPrototype(), $nasgenmap$);
}
private NativeNumber(final double value) {
@@ -185,7 +185,7 @@ public final class NativeNumber extends ScriptObject {
* @return number in decimal fixed point notation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toFixed(final Object self, final Object fractionDigits) {
+ public static String toFixed(final Object self, final Object fractionDigits) {
final int f = JSType.toInteger(fractionDigits);
if (f < 0 || f > 20) {
throw rangeError("invalid.fraction.digits", "toFixed");
@@ -217,7 +217,7 @@ public final class NativeNumber extends ScriptObject {
* @return number in decimal exponential notation
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toExponential(final Object self, final Object fractionDigits) {
+ public static String toExponential(final Object self, final Object fractionDigits) {
final double x = getNumberValue(self);
final boolean trimZeros = fractionDigits == UNDEFINED;
final int f = trimZeros ? 16 : JSType.toInteger(fractionDigits);
@@ -245,7 +245,7 @@ public final class NativeNumber extends ScriptObject {
* @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toPrecision(final Object self, final Object precision) {
+ public static String toPrecision(final Object self, final Object precision) {
final double x = getNumberValue(self);
if (precision == UNDEFINED) {
return JSType.toString(x);
@@ -278,7 +278,7 @@ public final class NativeNumber extends ScriptObject {
* @return string representation of this Number in the given radix
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self, final Object radix) {
+ public static String toString(final Object self, final Object radix) {
if (radix != UNDEFINED) {
final int intRadix = JSType.toInteger(radix);
if (intRadix != 10) {
@@ -299,7 +299,7 @@ public final class NativeNumber extends ScriptObject {
* @return localized string for this Number
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleString(final Object self) {
+ public static String toLocaleString(final Object self) {
return JSType.toString(getNumberValue(self));
}
@@ -308,10 +308,10 @@ public final class NativeNumber extends ScriptObject {
* ECMA 15.7.4.4 Number.prototype.valueOf ( )
*
* @param self self reference
- * @return boxed number value for this Number
+ * @return number value for this Number
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static double valueOf(final Object self) {
return getNumberValue(self);
}
@@ -322,7 +322,7 @@ public final class NativeNumber extends ScriptObject {
* @return Link to be invoked at call site.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
- return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, Number.class, new NativeNumber(((Number)receiver).doubleValue()), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
@@ -330,6 +330,11 @@ public final class NativeNumber extends ScriptObject {
return new NativeNumber(((Number)receiver).doubleValue());
}
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getNumberPrototype();
+ }
+
private static double getNumberValue(final Object self) {
if (self instanceof Number) {
return ((Number)self).doubleValue();
@@ -378,7 +383,7 @@ public final class NativeNumber extends ScriptObject {
return str;
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, "wrapFilter", MH.type(NativeNumber.class, Object.class));
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeNumber.class, name, type);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index d102c0fb..9cde4faf 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -31,6 +31,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -58,6 +59,7 @@ import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
import jdk.nashorn.internal.runtime.linker.NashornBeansLinker;
@@ -101,6 +103,27 @@ public final class NativeObject {
}
/**
+ * Nashorn extension: setIndexedPropertiesToExternalArrayData
+ *
+ * @param self self reference
+ * @param obj object whose index properties are backed by buffer
+ * @param buf external buffer - should be a nio ByteBuffer
+ * @return the 'obj' object
+ */
+ @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+ public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
+ Global.checkObject(obj);
+ final ScriptObject sobj = (ScriptObject)obj;
+ if (buf instanceof ByteBuffer) {
+ sobj.setArray(ArrayData.allocate((ByteBuffer)buf));
+ } else {
+ throw typeError("not.a.bytebuffer", "setIndexedPropertiesToExternalArrayData's buf argument");
+ }
+ return sobj;
+ }
+
+
+ /**
* ECMA 15.2.3.2 Object.getPrototypeOf ( O )
*
* @param self self reference
@@ -180,7 +203,7 @@ public final class NativeObject {
* @return array of property names
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object getOwnPropertyNames(final Object self, final Object obj) {
+ public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
} else if (obj instanceof ScriptObjectMirror) {
@@ -199,7 +222,7 @@ public final class NativeObject {
* @return object created
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object create(final Object self, final Object proto, final Object props) {
+ public static ScriptObject create(final Object self, final Object proto, final Object props) {
if (proto != null) {
Global.checkObject(proto);
}
@@ -225,10 +248,11 @@ public final class NativeObject {
* @return object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
+ public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
Global.checkObject(obj);
- ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true);
- return obj;
+ final ScriptObject sobj = (ScriptObject)obj;
+ sobj.defineOwnProperty(JSType.toString(prop), attr, true);
+ return sobj;
}
/**
@@ -240,7 +264,7 @@ public final class NativeObject {
* @return object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object defineProperties(final Object self, final Object obj, final Object props) {
+ public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
Global.checkObject(obj);
final ScriptObject sobj = (ScriptObject)obj;
@@ -319,7 +343,7 @@ public final class NativeObject {
* @return true if sealed, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isSealed(final Object self, final Object obj) {
+ public static boolean isSealed(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isSealed();
} else if (obj instanceof ScriptObjectMirror) {
@@ -337,7 +361,7 @@ public final class NativeObject {
* @return true if object is frozen, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isFrozen(final Object self, final Object obj) {
+ public static boolean isFrozen(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isFrozen();
} else if (obj instanceof ScriptObjectMirror) {
@@ -355,7 +379,7 @@ public final class NativeObject {
* @return true if object is extensible, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object isExtensible(final Object self, final Object obj) {
+ public static boolean isExtensible(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).isExtensible();
} else if (obj instanceof ScriptObjectMirror) {
@@ -373,7 +397,7 @@ public final class NativeObject {
* @return array of keys in object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object keys(final Object self, final Object obj) {
+ public static ScriptObject keys(final Object self, final Object obj) {
if (obj instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)obj;
return new NativeArray(sobj.getOwnKeys(false));
@@ -430,7 +454,7 @@ public final class NativeObject {
* @return ToString of object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return ScriptRuntime.builtinObjectToString(self);
}
@@ -483,7 +507,7 @@ public final class NativeObject {
* @return true if property exists in object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object hasOwnProperty(final Object self, final Object v) {
+ public static boolean hasOwnProperty(final Object self, final Object v) {
// Convert ScriptObjects to primitive with String.class hint
// but no need to convert other primitives to string.
final Object key = JSType.toPrimitive(v, String.class);
@@ -500,7 +524,7 @@ public final class NativeObject {
* @return true if object is prototype of v
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object isPrototypeOf(final Object self, final Object v) {
+ public static boolean isPrototypeOf(final Object self, final Object v) {
if (!(v instanceof ScriptObject)) {
return false;
}
@@ -526,7 +550,7 @@ public final class NativeObject {
* @return true if property is enumerable
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object propertyIsEnumerable(final Object self, final Object v) {
+ public static boolean propertyIsEnumerable(final Object self, final Object v) {
final String str = JSType.toString(v);
final Object obj = Global.toObject(self);
diff --git a/src/jdk/nashorn/internal/objects/NativeRangeError.java b/src/jdk/nashorn/internal/objects/NativeRangeError.java
index d51a0c09..ff3ac7b7 100644
--- a/src/jdk/nashorn/internal/objects/NativeRangeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeRangeError.java
@@ -44,7 +44,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeRangeError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@ public final class NativeRangeError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeRangeError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@ public final class NativeRangeError extends ScriptObject {
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeRangeError(final Object msg, final Global global) {
- this(msg, global.getRangeErrorPrototype(), global.getRangeErrorMap());
+ this(msg, global.getRangeErrorPrototype(), $nasgenmap$);
}
private NativeRangeError(final Object msg) {
@@ -96,7 +98,7 @@ public final class NativeRangeError extends ScriptObject {
* @return new RangeError
*/
@Constructor(name = "RangeError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeRangeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeRangeError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeReferenceError.java b/src/jdk/nashorn/internal/objects/NativeReferenceError.java
index a269b515..74190179 100644
--- a/src/jdk/nashorn/internal/objects/NativeReferenceError.java
+++ b/src/jdk/nashorn/internal/objects/NativeReferenceError.java
@@ -44,7 +44,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeReferenceError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,13 +55,14 @@ public final class NativeReferenceError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
private NativeReferenceError(final Object msg, final ScriptObject proto, final PropertyMap map) {
super(proto, map);
if (msg != UNDEFINED) {
@@ -69,10 +70,11 @@ public final class NativeReferenceError extends ScriptObject {
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
NativeReferenceError(final Object msg, final Global global) {
- this(msg, global.getReferenceErrorPrototype(), global.getReferenceErrorMap());
+ this(msg, global.getReferenceErrorPrototype(), $nasgenmap$);
}
private NativeReferenceError(final Object msg) {
@@ -96,7 +98,7 @@ public final class NativeReferenceError extends ScriptObject {
* @return new ReferenceError
*/
@Constructor(name = "ReferenceError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeReferenceError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeReferenceError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExp.java b/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 318ca2a0..89a9a828 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -70,12 +70,8 @@ public final class NativeRegExp extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeRegExp(final Global global) {
- super(global.getRegExpPrototype(), global.getRegExpMap());
+ super(global.getRegExpPrototype(), $nasgenmap$);
this.globalObject = global;
}
@@ -126,7 +122,7 @@ public final class NativeRegExp extends ScriptObject {
* @return new NativeRegExp
*/
@Constructor(arity = 2)
- public static Object constructor(final boolean isNew, final Object self, final Object... args) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object... args) {
if (args.length > 1) {
return newRegExp(args[0], args[1]);
} else if (args.length > 0) {
@@ -146,7 +142,7 @@ public final class NativeRegExp extends ScriptObject {
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self) {
return new NativeRegExp("", "");
}
@@ -161,7 +157,7 @@ public final class NativeRegExp extends ScriptObject {
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self, final Object pattern) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern) {
return newRegExp(pattern, UNDEFINED);
}
@@ -177,7 +173,7 @@ public final class NativeRegExp extends ScriptObject {
* @return new NativeRegExp
*/
@SpecializedConstructor
- public static Object constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
+ public static NativeRegExp constructor(final boolean isNew, final Object self, final Object pattern, final Object flags) {
return newRegExp(pattern, flags);
}
@@ -287,7 +283,7 @@ public final class NativeRegExp extends ScriptObject {
* @return new NativeRegExp
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object compile(final Object self, final Object pattern, final Object flags) {
+ public static ScriptObject compile(final Object self, final Object pattern, final Object flags) {
final NativeRegExp regExp = checkRegExp(self);
final NativeRegExp compiled = newRegExp(pattern, flags);
// copy over regexp to 'self'
@@ -306,7 +302,7 @@ public final class NativeRegExp extends ScriptObject {
* @return array containing the matches or {@code null} if no match
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object exec(final Object self, final Object string) {
+ public static ScriptObject exec(final Object self, final Object string) {
return checkRegExp(self).exec(JSType.toString(string));
}
@@ -318,7 +314,7 @@ public final class NativeRegExp extends ScriptObject {
* @return true if matches found, false otherwise
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object test(final Object self, final Object string) {
+ public static boolean test(final Object self, final Object string) {
return checkRegExp(self).test(JSType.toString(string));
}
@@ -329,7 +325,7 @@ public final class NativeRegExp extends ScriptObject {
* @return string version of regexp
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return checkRegExp(self).toString();
}
@@ -622,7 +618,7 @@ public final class NativeRegExp extends ScriptObject {
* @param string String to match.
* @return NativeArray of matches, string or null.
*/
- public Object exec(final String string) {
+ public NativeRegExpExecResult exec(final String string) {
final RegExpResult match = execInner(string);
if (match == null) {
@@ -639,7 +635,7 @@ public final class NativeRegExp extends ScriptObject {
* @param string String to match.
* @return True if a match is found.
*/
- public Object test(final String string) {
+ public boolean test(final String string) {
return execInner(string) != null;
}
@@ -653,7 +649,7 @@ public final class NativeRegExp extends ScriptObject {
* @param replacement Replacement string.
* @return String with substitutions.
*/
- Object replace(final String string, final String replacement, final ScriptFunction function) {
+ String replace(final String string, final String replacement, final ScriptFunction function) {
final RegExpMatcher matcher = regexp.match(string);
if (matcher == null) {
@@ -808,7 +804,7 @@ public final class NativeRegExp extends ScriptObject {
* @param limit Split limit.
* @return Array of substrings.
*/
- Object split(final String string, final long limit) {
+ NativeArray split(final String string, final long limit) {
if (limit == 0L) {
return new NativeArray();
}
@@ -871,7 +867,7 @@ public final class NativeRegExp extends ScriptObject {
* @param string String to match.
* @return Index of match.
*/
- Object search(final String string) {
+ int search(final String string) {
final RegExpResult match = execInner(string);
if (match == null) {
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
index 3508e5f6..f12cea12 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
@@ -53,12 +53,8 @@ public final class NativeRegExpExecResult extends ScriptObject {
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
NativeRegExpExecResult(final RegExpResult result, final Global global) {
- super(global.getArrayPrototype(), global.getRegExpExecResultMap());
+ super(global.getArrayPrototype(), $nasgenmap$);
setIsArray();
this.setArray(ArrayData.allocate(result.getGroups().clone()));
this.index = result.getIndex();
diff --git a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
index b81cc2af..dd2c2816 100644
--- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
+++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
@@ -60,9 +60,9 @@ public final class NativeStrictArguments extends ScriptObject {
// In strict mode, the caller and callee properties should throw TypeError
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
- map = map.addProperty(map.newUserAccessors("caller", flags));
- map = map.addProperty(map.newUserAccessors("callee", flags));
- map$ = map.setIsShared();
+ map = map.addPropertyNoHistory(map.newUserAccessors("caller", flags));
+ map = map.addPropertyNoHistory(map.newUserAccessors("callee", flags));
+ map$ = map;
}
static PropertyMap getInitialMap() {
diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java
index 95af71a6..51edf75a 100644
--- a/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/src/jdk/nashorn/internal/objects/NativeString.java
@@ -32,6 +32,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
@@ -69,21 +70,20 @@ public final class NativeString extends ScriptObject {
private final CharSequence value;
- static final MethodHandle WRAPFILTER = findWrapFilter();
+ // Method handle to create an object wrapper for a primitive string
+ private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", MH.type(NativeString.class, Object.class));
+ // Method handle to retrieve the String prototype object
+ private static final MethodHandle PROTOFILTER = findOwnMH("protoFilter", MH.type(Object.class, Object.class));
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
private NativeString(final CharSequence value) {
this(value, Global.instance());
}
NativeString(final CharSequence value, final Global global) {
- this(value, global.getStringPrototype(), global.getStringMap());
+ this(value, global.getStringPrototype(), $nasgenmap$);
}
private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) {
@@ -425,7 +425,7 @@ public final class NativeString extends ScriptObject {
* @return string with arguments translated to charcodes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1, where = Where.CONSTRUCTOR)
- public static Object fromCharCode(final Object self, final Object... args) {
+ public static String fromCharCode(final Object self, final Object... args) {
final char[] buf = new char[args.length];
int index = 0;
for (final Object arg : args) {
@@ -441,7 +441,7 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final Object value) {
+ public static String fromCharCode(final Object self, final Object value) {
try {
return "" + (char)JSType.toUint16(((Number)value).doubleValue());
} catch (final ClassCastException e) {
@@ -456,7 +456,7 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final int value) {
+ public static String fromCharCode(final Object self, final int value) {
return "" + (char)(value & 0xffff);
}
@@ -467,7 +467,7 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final long value) {
+ public static String fromCharCode(final Object self, final long value) {
return "" + (char)((int)value & 0xffff);
}
@@ -478,7 +478,7 @@ public final class NativeString extends ScriptObject {
* @return string with one charcode
*/
@SpecializedFunction
- public static Object fromCharCode(final Object self, final double value) {
+ public static String fromCharCode(final Object self, final double value) {
return "" + (char)JSType.toUint16(value);
}
@@ -488,7 +488,7 @@ public final class NativeString extends ScriptObject {
* @return self as string
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toString(final Object self) {
+ public static String toString(final Object self) {
return getString(self);
}
@@ -498,7 +498,7 @@ public final class NativeString extends ScriptObject {
* @return self as string
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object valueOf(final Object self) {
+ public static String valueOf(final Object self) {
return getString(self);
}
@@ -509,7 +509,7 @@ public final class NativeString extends ScriptObject {
* @return string representing the char at the given position
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object charAt(final Object self, final Object pos) {
+ public static String charAt(final Object self, final Object pos) {
return charAtImpl(checkObjectToString(self), JSType.toInteger(pos));
}
@@ -546,7 +546,7 @@ public final class NativeString extends ScriptObject {
* @return number representing charcode at position
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object charCodeAt(final Object self, final Object pos) {
+ public static double charCodeAt(final Object self, final Object pos) {
return charCodeAtImpl(checkObjectToString(self), JSType.toInteger(pos));
}
@@ -601,7 +601,7 @@ public final class NativeString extends ScriptObject {
* @return position of first match or -1
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object indexOf(final Object self, final Object search, final Object pos) {
+ public static int indexOf(final Object self, final Object search, final Object pos) {
final String str = checkObjectToString(self);
return str.indexOf(JSType.toString(search), JSType.toInteger(pos));
}
@@ -649,7 +649,7 @@ public final class NativeString extends ScriptObject {
* @return last position of match or -1
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static Object lastIndexOf(final Object self, final Object search, final Object pos) {
+ public static int lastIndexOf(final Object self, final Object search, final Object pos) {
final String str = checkObjectToString(self);
final String searchStr = JSType.toString(search);
@@ -680,7 +680,7 @@ public final class NativeString extends ScriptObject {
* @return result of locale sensitive comparison operation between {@code self} and {@code that}
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object localeCompare(final Object self, final Object that) {
+ public static double localeCompare(final Object self, final Object that) {
final String str = checkObjectToString(self);
final Collator collator = Collator.getInstance(Global.getEnv()._locale);
@@ -698,7 +698,7 @@ public final class NativeString extends ScriptObject {
* @return array of regexp matches
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object match(final Object self, final Object regexp) {
+ public static ScriptObject match(final Object self, final Object regexp) {
final String str = checkObjectToString(self);
@@ -745,7 +745,7 @@ public final class NativeString extends ScriptObject {
* @return string after replacement
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object replace(final Object self, final Object string, final Object replacement) {
+ public static String replace(final Object self, final Object string, final Object replacement) {
final String str = checkObjectToString(self);
@@ -771,7 +771,7 @@ public final class NativeString extends ScriptObject {
* @return offset where match occurred
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object search(final Object self, final Object string) {
+ public static int search(final Object self, final Object string) {
final String str = checkObjectToString(self);
final NativeRegExp nativeRegExp = Global.toRegExp(string == UNDEFINED ? "" : string);
@@ -788,7 +788,7 @@ public final class NativeString extends ScriptObject {
* @return sliced out substring
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object slice(final Object self, final Object start, final Object end) {
+ public static String slice(final Object self, final Object start, final Object end) {
final String str = checkObjectToString(self);
if (end == UNDEFINED) {
@@ -805,7 +805,7 @@ public final class NativeString extends ScriptObject {
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final int start) {
+ public static String slice(final Object self, final int start) {
final String str = checkObjectToString(self);
final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
@@ -820,7 +820,7 @@ public final class NativeString extends ScriptObject {
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final double start) {
+ public static String slice(final Object self, final double start) {
return slice(self, (int)start);
}
@@ -833,7 +833,7 @@ public final class NativeString extends ScriptObject {
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final int start, final int end) {
+ public static String slice(final Object self, final int start, final int end) {
final String str = checkObjectToString(self);
final int len = str.length();
@@ -853,7 +853,7 @@ public final class NativeString extends ScriptObject {
* @return sliced out substring
*/
@SpecializedFunction
- public static Object slice(final Object self, final double start, final double end) {
+ public static String slice(final Object self, final double start, final double end) {
return slice(self, (int)start, (int)end);
}
@@ -866,7 +866,7 @@ public final class NativeString extends ScriptObject {
* @return array object in which splits have been placed
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object split(final Object self, final Object separator, final Object limit) {
+ public static ScriptObject split(final Object self, final Object separator, final Object limit) {
final String str = checkObjectToString(self);
final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
@@ -882,7 +882,7 @@ public final class NativeString extends ScriptObject {
return splitString(str, JSType.toString(separator), lim);
}
- private static Object splitString(String str, String separator, long limit) {
+ private static ScriptObject splitString(String str, String separator, long limit) {
if (separator.isEmpty()) {
final int length = (int) Math.min(str.length(), limit);
final Object[] array = new Object[length];
@@ -923,7 +923,7 @@ public final class NativeString extends ScriptObject {
* @return substring given start and length of section
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object substr(final Object self, final Object start, final Object length) {
+ public static String substr(final Object self, final Object start, final Object length) {
final String str = JSType.toString(self);
final int strLength = str.length();
@@ -946,7 +946,7 @@ public final class NativeString extends ScriptObject {
* @return substring given start and end indexes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object substring(final Object self, final Object start, final Object end) {
+ public static String substring(final Object self, final Object start, final Object end) {
final String str = checkObjectToString(self);
if (end == UNDEFINED) {
@@ -1026,7 +1026,7 @@ public final class NativeString extends ScriptObject {
* @return string to lower case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLowerCase(final Object self) {
+ public static String toLowerCase(final Object self) {
return checkObjectToString(self).toLowerCase(Locale.ROOT);
}
@@ -1036,7 +1036,7 @@ public final class NativeString extends ScriptObject {
* @return string to locale sensitive lower case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleLowerCase(final Object self) {
+ public static String toLocaleLowerCase(final Object self) {
return checkObjectToString(self).toLowerCase(Global.getEnv()._locale);
}
@@ -1046,7 +1046,7 @@ public final class NativeString extends ScriptObject {
* @return string to upper case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toUpperCase(final Object self) {
+ public static String toUpperCase(final Object self) {
return checkObjectToString(self).toUpperCase(Locale.ROOT);
}
@@ -1056,7 +1056,7 @@ public final class NativeString extends ScriptObject {
* @return string to locale sensitive upper case
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toLocaleUpperCase(final Object self) {
+ public static String toLocaleUpperCase(final Object self) {
return checkObjectToString(self).toUpperCase(Global.getEnv()._locale);
}
@@ -1066,7 +1066,7 @@ public final class NativeString extends ScriptObject {
* @return string trimmed from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trim(final Object self) {
+ public static String trim(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1088,7 +1088,7 @@ public final class NativeString extends ScriptObject {
* @return string trimmed left from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trimLeft(final Object self) {
+ public static String trimLeft(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1107,7 +1107,7 @@ public final class NativeString extends ScriptObject {
* @return string trimmed right from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object trimRight(final Object self) {
+ public static String trimRight(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
@@ -1120,7 +1120,7 @@ public final class NativeString extends ScriptObject {
return str.substring(start, end + 1);
}
- private static Object newObj(final Object self, final CharSequence str) {
+ private static ScriptObject newObj(final Object self, final CharSequence str) {
return new NativeString(str);
}
@@ -1199,7 +1199,7 @@ public final class NativeString extends ScriptObject {
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Object receiver) {
final MethodHandle guard = NashornGuards.getInstanceOf2Guard(String.class, ConsString.class);
- return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER);
+ return PrimitiveLookup.lookupPrimitive(request, guard, new NativeString((CharSequence)receiver), WRAPFILTER, PROTOFILTER);
}
@SuppressWarnings("unused")
@@ -1207,6 +1207,11 @@ public final class NativeString extends ScriptObject {
return new NativeString((CharSequence)receiver);
}
+ @SuppressWarnings("unused")
+ private static Object protoFilter(final Object object) {
+ return Global.instance().getStringPrototype();
+ }
+
private static CharSequence getCharSequence(final Object self) {
if (self instanceof String || self instanceof ConsString) {
return (CharSequence)self;
@@ -1254,7 +1259,7 @@ public final class NativeString extends ScriptObject {
return key >= 0 && key < value.length();
}
- private static MethodHandle findWrapFilter() {
- return MH.findStatic(MethodHandles.lookup(), NativeString.class, "wrapFilter", MH.type(NativeString.class, Object.class));
+ private static MethodHandle findOwnMH(final String name, final MethodType type) {
+ return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
index 45920ba7..db7debb0 100644
--- a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
+++ b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
@@ -44,7 +44,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeSyntaxError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,20 +55,22 @@ public final class NativeSyntaxError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeSyntaxError(final Object msg, final Global global) {
- super(global.getSyntaxErrorPrototype(), global.getSyntaxErrorMap());
+ super(global.getSyntaxErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeSyntaxError(final Object msg) {
@@ -92,7 +94,7 @@ public final class NativeSyntaxError extends ScriptObject {
* @return new SyntaxError
*/
@Constructor(name = "SyntaxError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeSyntaxError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeSyntaxError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeTypeError.java b/src/jdk/nashorn/internal/objects/NativeTypeError.java
index 2b2308b1..6e5a4934 100644
--- a/src/jdk/nashorn/internal/objects/NativeTypeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeTypeError.java
@@ -44,7 +44,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeTypeError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -55,20 +55,22 @@ public final class NativeTypeError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeTypeError(final Object msg, final Global global) {
- super(global.getTypeErrorPrototype(), global.getTypeErrorMap());
+ super(global.getTypeErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeTypeError(final Object msg) {
@@ -92,7 +94,7 @@ public final class NativeTypeError extends ScriptObject {
* @return new TypeError
*/
@Constructor(name = "TypeError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeTypeError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeTypeError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeURIError.java b/src/jdk/nashorn/internal/objects/NativeURIError.java
index 2caf1369..cf5fdaa0 100644
--- a/src/jdk/nashorn/internal/objects/NativeURIError.java
+++ b/src/jdk/nashorn/internal/objects/NativeURIError.java
@@ -43,7 +43,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
public final class NativeURIError extends ScriptObject {
/** message property in instance */
- @Property(name = NativeError.MESSAGE)
+ @Property(name = NativeError.MESSAGE, attributes = Attribute.NOT_ENUMERABLE)
public Object instMessage;
/** error name property */
@@ -54,20 +54,22 @@ public final class NativeURIError extends ScriptObject {
@Property(attributes = Attribute.NOT_ENUMERABLE, where = Where.PROTOTYPE)
public Object message;
+ /** Nashorn extension: underlying exception */
+ @Property(attributes = Attribute.NOT_ENUMERABLE)
+ public Object nashornException;
+
// initialized by nasgen
private static PropertyMap $nasgenmap$;
- static PropertyMap getInitialMap() {
- return $nasgenmap$;
- }
-
+ @SuppressWarnings("LeakingThisInConstructor")
NativeURIError(final Object msg, final Global global) {
- super(global.getURIErrorPrototype(), global.getURIErrorMap());
+ super(global.getURIErrorPrototype(), $nasgenmap$);
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
this.delete(NativeError.MESSAGE, false);
}
+ NativeError.initException(this);
}
private NativeURIError(final Object msg) {
@@ -91,7 +93,7 @@ public final class NativeURIError extends ScriptObject {
* @return new URIError
*/
@Constructor(name = "URIError")
- public static Object constructor(final boolean newObj, final Object self, final Object msg) {
+ public static NativeURIError constructor(final boolean newObj, final Object self, final Object msg) {
return new NativeURIError(msg);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index ee91aef3..8aa3d628 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -99,8 +99,8 @@ public final class NativeUint16Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint16Array)constructorImpl(args, FACTORY);
}
NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -150,8 +150,8 @@ public final class NativeUint16Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint16Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint16Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 58909dba..73812246 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -118,8 +118,8 @@ public final class NativeUint32Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint32Array)constructorImpl(args, FACTORY);
}
NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -169,8 +169,8 @@ public final class NativeUint32Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint32Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint32Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 0db1bee6..1f304563 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -92,8 +92,8 @@ public final class NativeUint8Array extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint8Array)constructorImpl(args, FACTORY);
}
NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -143,8 +143,8 @@ public final class NativeUint8Array extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint8Array subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint8Array)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index f0db743c..d69adc10 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -89,6 +89,15 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
}
@Override
+ protected void setImpl(final int index, final long value) {
+ if (JSType.isRepresentableAsInt(value)) {
+ setImpl(index, (int)value);
+ } else {
+ buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0;
+ }
+ }
+
+ @Override
protected void setImpl(final int key, final double value) {
setImpl(key, (int)Math.rint(value));
}
@@ -109,8 +118,8 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
* @return new typed array
*/
@Constructor(arity = 1)
- public static Object constructor(final boolean newObj, final Object self, final Object... args) {
- return constructorImpl(args, FACTORY);
+ public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
+ return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
}
NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -160,8 +169,8 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
* @return sub array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
- protected static Object subarray(final Object self, final Object begin, final Object end) {
- return ArrayBufferView.subarrayImpl(self, begin, end);
+ protected static NativeUint8ClampedArray subarray(final Object self, final Object begin, final Object end) {
+ return (NativeUint8ClampedArray)ArrayBufferView.subarrayImpl(self, begin, end);
}
@Override
diff --git a/src/jdk/nashorn/internal/objects/PrototypeObject.java b/src/jdk/nashorn/internal/objects/PrototypeObject.java
index 4610afc2..483f6174 100644
--- a/src/jdk/nashorn/internal/objects/PrototypeObject.java
+++ b/src/jdk/nashorn/internal/objects/PrototypeObject.java
@@ -54,16 +54,11 @@ public class PrototypeObject extends ScriptObject {
static {
final ArrayList<Property> properties = new ArrayList<>(1);
properties.add(AccessorProperty.create("constructor", Property.NOT_ENUMERABLE, GET_CONSTRUCTOR, SET_CONSTRUCTOR));
- map$ = PropertyMap.newMap(properties).setIsShared();
- }
-
- static PropertyMap getInitialMap() {
- return map$;
+ map$ = PropertyMap.newMap(properties);
}
private PrototypeObject(final Global global, final PropertyMap map) {
- super(map != map$? map.addAll(global.getPrototypeObjectMap()) : global.getPrototypeObjectMap());
- setProto(global.getObjectPrototype());
+ super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
}
PrototypeObject() {
diff --git a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index f0bea3a6..dcbc7da9 100644
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -37,7 +37,6 @@ import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptFunctionData;
import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.AccessorProperty;
/**
@@ -56,27 +55,11 @@ public class ScriptFunctionImpl extends ScriptFunction {
// property map for non-strict, non-bound functions.
private static final PropertyMap map$;
- static PropertyMap getInitialMap() {
- return map$;
- }
-
- static PropertyMap getInitialAnonymousMap() {
- return AnonymousFunction.getInitialMap();
- }
-
- static PropertyMap getInitialStrictMap() {
- return strictmodemap$;
- }
-
- static PropertyMap getInitialBoundMap() {
- return boundfunctionmap$;
- }
-
// Marker object for lazily initialized prototype object
private static final Object LAZY_PROTOTYPE = new Object();
private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final MethodHandle[] specs, final Global global) {
- super(name, invokeHandle, global.getFunctionMap(), null, specs, false, true, true);
+ super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -93,7 +76,7 @@ public class ScriptFunctionImpl extends ScriptFunction {
}
private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final MethodHandle[] specs, final Global global) {
- super(name, invokeHandle, map.addAll(global.getFunctionMap()), null, specs, false, true, true);
+ super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
init(global);
}
@@ -110,8 +93,8 @@ public class ScriptFunctionImpl extends ScriptFunction {
this(name, invokeHandle, map, specs, Global.instance());
}
- private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor, final Global global) {
- super(name, methodHandle, getMap(global, isStrict), scope, specs, isStrict, isBuiltin, isConstructor);
+ private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags, final Global global) {
+ super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags);
init(global);
}
@@ -122,16 +105,14 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param methodHandle handle for invocation
* @param scope scope object
* @param specs specialized versions of this method, if available, null otherwise
- * @param isStrict are we in strict mode
- * @param isBuiltin is this a built-in function
- * @param isConstructor can the function be used as a constructor (most can; some built-ins are restricted).
+ * @param flags {@link ScriptFunctionData} flags
*/
- ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- this(name, methodHandle, scope, specs, isStrict, isBuiltin, isConstructor, Global.instance());
+ ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final MethodHandle[] specs, final int flags) {
+ this(name, methodHandle, scope, specs, flags, Global.instance());
}
private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) {
- super(data, getMap(global, data.isStrict()), scope);
+ super(data, getMap(data.isStrict()), scope);
init(global);
}
@@ -151,7 +132,7 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @param global the global object
*/
ScriptFunctionImpl(final ScriptFunctionData data, final Global global) {
- super(data, global.getBoundFunctionMap(), null);
+ super(data, boundfunctionmap$, null);
init(global);
}
@@ -163,25 +144,24 @@ public class ScriptFunctionImpl extends ScriptFunction {
map$ = PropertyMap.newMap(properties);
strictmodemap$ = createStrictModeMap(map$);
boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
- // There are order dependencies between normal map, struct map and bound map
- // We can make these 'shared' only after initialization of all three.
- map$.setIsShared();
- strictmodemap$.setIsShared();
- boundfunctionmap$.setIsShared();
}
private static PropertyMap createStrictModeMap(final PropertyMap map) {
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
PropertyMap newMap = map;
// Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
- newMap = newMap.addProperty(map.newUserAccessors("arguments", flags));
- newMap = newMap.addProperty(map.newUserAccessors("caller", flags));
+ newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
+ newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
return newMap;
}
+ private static boolean isStrict(final int flags) {
+ return (flags & ScriptFunctionData.IS_STRICT) != 0;
+ }
+
// Choose the map based on strict mode!
- private static PropertyMap getMap(final Global global, final boolean strict) {
- return strict ? global.getStrictFunctionMap() : global.getFunctionMap();
+ private static PropertyMap getMap(final boolean strict) {
+ return strict ? strictmodemap$ : map$;
}
private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
@@ -193,14 +173,10 @@ public class ScriptFunctionImpl extends ScriptFunction {
// Instance of this class is used as global anonymous function which
// serves as Function.prototype object.
private static class AnonymousFunction extends ScriptFunctionImpl {
- private static final PropertyMap anonmap$ = PropertyMap.newMap().setIsShared();
-
- static PropertyMap getInitialMap() {
- return anonmap$;
- }
+ private static final PropertyMap anonmap$ = PropertyMap.newMap();
AnonymousFunction(final Global global) {
- super("", GlobalFunctions.ANONYMOUS, global.getAnonymousFunctionMap(), null);
+ super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
}
}
@@ -217,7 +193,7 @@ public class ScriptFunctionImpl extends ScriptFunction {
* @return new ScriptFunction
*/
static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
- final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, false, true, false);
+ final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
func.setPrototype(UNDEFINED);
// Non-constructor built-in functions do not have "prototype" property
func.deleteOwnProperty(func.getMap().findProperty("prototype"));
@@ -281,13 +257,17 @@ public class ScriptFunctionImpl extends ScriptFunction {
}
@Override
- public final void setPrototype(final Object prototype) {
- this.prototype = prototype;
+ public final void setPrototype(final Object newProto) {
+ if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) {
+ // Replace our current allocator map with one that is associated with the new prototype.
+ allocatorMap = allocatorMap.changeProto((ScriptObject)newProto);
+ }
+ this.prototype = newProto;
}
// Internals below..
private void init(final Global global) {
- this.setProto(global.getFunctionPrototype());
+ this.setInitialProto(global.getFunctionPrototype());
this.prototype = LAZY_PROTOTYPE;
// We have to fill user accessor functions late as these are stored
diff --git a/src/jdk/nashorn/internal/parser/AbstractParser.java b/src/jdk/nashorn/internal/parser/AbstractParser.java
index 587ae869..d4a42ba4 100644
--- a/src/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
import static jdk.nashorn.internal.parser.TokenType.IDENT;
@@ -84,6 +85,9 @@ public abstract class AbstractParser {
/** Is this parser running under strict mode? */
protected boolean isStrictMode;
+ /** //@ sourceURL or //# sourceURL */
+ protected String sourceURL;
+
/**
* Construct a parser.
*
@@ -156,17 +160,38 @@ public abstract class AbstractParser {
protected final TokenType nextOrEOL() {
do {
nextToken();
- } while (type == COMMENT);
+ if (type == DIRECTIVE_COMMENT) {
+ checkDirectiveComment();
+ }
+ } while (type == COMMENT || type == DIRECTIVE_COMMENT);
return type;
}
+ // sourceURL= after directive comment
+ private static final String SOURCE_URL_PREFIX = "sourceURL=";
+
+ // currently only @sourceURL=foo supported
+ private void checkDirectiveComment() {
+ // if already set, ignore this one
+ if (sourceURL != null) {
+ return;
+ }
+
+ final String comment = (String) lexer.getValueOf(token, isStrictMode);
+ final int len = comment.length();
+ // 4 characters for directive comment marker //@\s or //#\s
+ if (len > 4 && comment.substring(4).startsWith(SOURCE_URL_PREFIX)) {
+ sourceURL = comment.substring(4 + SOURCE_URL_PREFIX.length());
+ }
+ }
+
/**
* Seek next token.
*
* @return tokenType of next token.
*/
- private final TokenType nextToken() {
+ private TokenType nextToken() {
// Capture last token tokenType.
last = type;
if (type != EOF) {
diff --git a/src/jdk/nashorn/internal/parser/Lexer.java b/src/jdk/nashorn/internal/parser/Lexer.java
index a01705dd..653f04c0 100644
--- a/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/src/jdk/nashorn/internal/parser/Lexer.java
@@ -27,6 +27,7 @@ package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.parser.TokenType.ADD;
import static jdk.nashorn.internal.parser.TokenType.COMMENT;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
import static jdk.nashorn.internal.parser.TokenType.EOF;
import static jdk.nashorn.internal.parser.TokenType.EOL;
@@ -434,12 +435,18 @@ public class Lexer extends Scanner {
if (ch1 == '/') {
// Skip over //.
skip(2);
+
+ boolean directiveComment = false;
+ if ((ch0 == '#' || ch0 == '@') && (ch1 == ' ')) {
+ directiveComment = true;
+ }
+
// Scan for EOL.
while (!atEOF() && !isEOL(ch0)) {
skip(1);
}
// Did detect a comment.
- add(COMMENT, start);
+ add(directiveComment? DIRECTIVE_COMMENT : COMMENT, start);
return true;
} else if (ch1 == '*') {
// Skip over /*.
@@ -1623,6 +1630,8 @@ public class Lexer extends Scanner {
return valueOfPattern(start, len); // RegexToken::LexerToken
case XML:
return valueOfXML(start, len); // XMLToken::LexerToken
+ case DIRECTIVE_COMMENT:
+ return source.getString(start, len);
default:
break;
}
diff --git a/src/jdk/nashorn/internal/parser/Parser.java b/src/jdk/nashorn/internal/parser/Parser.java
index 8e04fdce..6ad60b58 100644
--- a/src/jdk/nashorn/internal/parser/Parser.java
+++ b/src/jdk/nashorn/internal/parser/Parser.java
@@ -26,13 +26,14 @@
package jdk.nashorn.internal.parser;
import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
-import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
import static jdk.nashorn.internal.parser.TokenType.CASE;
import static jdk.nashorn.internal.parser.TokenType.CATCH;
import static jdk.nashorn.internal.parser.TokenType.COLON;
import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
+import static jdk.nashorn.internal.parser.TokenType.CONST;
import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
import static jdk.nashorn.internal.parser.TokenType.ELSE;
@@ -389,7 +390,9 @@ loop:
sb.append(parentFunction.getName()).append('$');
}
- sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.symbolName());
+ assert ident.getName() != null;
+ sb.append(ident.getName());
+
final String name = namespace.uniqueName(sb.toString());
assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName()) : "name = " + name;// must not rename runScript().
@@ -419,7 +422,8 @@ loop:
name,
parameters,
kind,
- flags);
+ flags,
+ sourceURL);
lc.push(functionNode);
// Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
@@ -638,6 +642,10 @@ loop:
script = restoreFunctionNode(script, token); //commit code
script = script.setBody(lc, script.getBody().setNeedsScope(lc));
+ // user may have directive comment to set sourceURL
+ if (sourceURL != null) {
+ script = script.setSourceURL(lc, sourceURL);
+ }
return script;
}
@@ -842,6 +850,11 @@ loop:
expect(SEMICOLON);
break;
default:
+ if (env._const_as_var && type == CONST) {
+ variableStatement(true);
+ break;
+ }
+
if (type == IDENT || isNonStrictModeIdent()) {
if (T(k + 1) == COLON) {
labelStatement();
@@ -1103,6 +1116,12 @@ loop:
case SEMICOLON:
break;
default:
+ if (env._const_as_var && type == CONST) {
+ // Var statements captured in for outer block.
+ vars = variableStatement(false);
+ break;
+ }
+
final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
forNode = forNode.setInit(lc, expression);
break;
@@ -1693,9 +1712,11 @@ loop:
// ECMA 12.4.1 strict mode restrictions
verifyStrictIdent(exception, "catch argument");
- // Check for conditional catch.
+ // Nashorn extension: catch clause can have optional
+ // condition. So, a single try can have more than one
+ // catch clause each with it's own condition.
final Expression ifExpression;
- if (type == IF) {
+ if (!env._no_syntax_extensions && type == IF) {
next();
// Get the exception condition.
ifExpression = expression();
@@ -1792,6 +1813,7 @@ loop:
case THIS:
final String name = type.getName();
next();
+ lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS);
return new IdentNode(primaryToken, finish, name);
case IDENT:
final IdentNode ident = getIdent();
@@ -2132,11 +2154,20 @@ loop:
final String setterName = setIdent.getPropertyName();
final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
expect(LPAREN);
- final IdentNode argIdent = getIdent();
- verifyStrictIdent(argIdent, "setter argument");
+ // be sloppy and allow missing setter parameter even though
+ // spec does not permit it!
+ final IdentNode argIdent;
+ if (type == IDENT || isNonStrictModeIdent()) {
+ argIdent = getIdent();
+ verifyStrictIdent(argIdent, "setter argument");
+ } else {
+ argIdent = null;
+ }
expect(RPAREN);
List<IdentNode> parameters = new ArrayList<>();
- parameters.add(argIdent);
+ if (argIdent != null) {
+ parameters.add(argIdent);
+ }
functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
@@ -2448,7 +2479,7 @@ loop:
// name is null, generate anonymous name
boolean isAnonymous = false;
if (name == null) {
- final String tmpName = "_L" + functionLine;
+ final String tmpName = ANON_FUNCTION_PREFIX.symbolName() + functionLine;
name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
isAnonymous = true;
}
diff --git a/src/jdk/nashorn/internal/parser/TokenType.java b/src/jdk/nashorn/internal/parser/TokenType.java
index 6287a234..59005077 100644
--- a/src/jdk/nashorn/internal/parser/TokenType.java
+++ b/src/jdk/nashorn/internal/parser/TokenType.java
@@ -41,10 +41,14 @@ import static jdk.nashorn.internal.parser.TokenKind.UNARY;
*/
@SuppressWarnings("javadoc")
public enum TokenType {
- ERROR (SPECIAL, null),
- EOF (SPECIAL, null),
- EOL (SPECIAL, null),
- COMMENT (SPECIAL, null),
+ ERROR (SPECIAL, null),
+ EOF (SPECIAL, null),
+ EOL (SPECIAL, null),
+ COMMENT (SPECIAL, null),
+ // comments of the form //@ foo=bar or //# foo=bar
+ // These comments are treated as special instructions
+ // to the lexer, parser or codegenerator.
+ DIRECTIVE_COMMENT (SPECIAL, null),
NOT (UNARY, "!", 14, false),
NE (BINARY, "!=", 9, true),
@@ -107,7 +111,7 @@ public enum TokenType {
CATCH (KEYWORD, "catch"),
// CHAR (FUTURE, "char"),
CLASS (FUTURE, "class"),
- CONST (FUTURE, "const"),
+ CONST (KEYWORD, "const"),
CONTINUE (KEYWORD, "continue"),
DEBUGGER (KEYWORD, "debugger"),
DEFAULT (KEYWORD, "default"),
diff --git a/src/jdk/nashorn/internal/runtime/AccessorProperty.java b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
index 702ca76b..e8ff153d 100644
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
@@ -39,6 +39,9 @@ import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getNumberOfAcces
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@@ -51,11 +54,12 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory;
* An AccessorProperty is the most generic property type. An AccessorProperty is
* represented as fields in a ScriptObject class.
*/
-public final class AccessorProperty extends Property {
+public final class AccessorProperty extends Property implements Serializable {
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class);
private static final int NOOF_TYPES = getNumberOfAccessorTypes();
+ private static final long serialVersionUID = 3371720170182154920L;
/**
* Properties in different maps for the same structure class will share their field getters and setters. This could
@@ -71,7 +75,7 @@ public final class AccessorProperty extends Property {
};
/** Property getter cache */
- private MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
+ private transient MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
@@ -122,16 +126,16 @@ public final class AccessorProperty extends Property {
}
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
- private MethodHandle primitiveGetter;
+ private transient MethodHandle primitiveGetter;
/** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
- private MethodHandle primitiveSetter;
+ private transient MethodHandle primitiveSetter;
/** Seed getter for the Object version of this field */
- private MethodHandle objectGetter;
+ private transient MethodHandle objectGetter;
/** Seed setter for the Object version of this field */
- private MethodHandle objectSetter;
+ private transient MethodHandle objectSetter;
/**
* Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
@@ -141,10 +145,12 @@ public final class AccessorProperty extends Property {
private Class<?> currentType;
/**
- * Delegate constructor. This is used when adding properties to the Global scope, which
- * is necessary for outermost levels in a script (the ScriptObject is represented by
- * a JO-prefixed ScriptObject class, but the properties need to be in the Global scope
- * and are thus rebound with that as receiver
+ * Delegate constructor for bound properties. This is used for properties created by
+ * {@link ScriptRuntime#mergeScope} and the Nashorn {@code Object.bindProperties} method.
+ * The former is used to add a script's defined globals to the current global scope while
+ * still storing them in a JO-prefixed ScriptObject class.
+ *
+ * <p>All properties created by this constructor have the {@link #IS_BOUND} flag set.</p>
*
* @param property accessor property to rebind
* @param delegate delegate object to rebind receiver to
@@ -157,6 +163,8 @@ public final class AccessorProperty extends Property {
this.objectGetter = bindTo(property.ensureObjectGetter(), delegate);
this.objectSetter = bindTo(property.ensureObjectSetter(), delegate);
+ // Properties created this way are bound to a delegate
+ this.flags |= IS_BOUND;
setCurrentType(property.getCurrentType());
}
@@ -239,6 +247,12 @@ public final class AccessorProperty extends Property {
public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) {
super(key, flags, slot);
+ initGetterSetter(structure);
+ }
+
+ private void initGetterSetter(final Class<?> structure) {
+ final int slot = getSlot();
+ final String key = getKey();
/*
* primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
* works in dual field mode, it only means that the property never has a primitive
@@ -301,6 +315,12 @@ public final class AccessorProperty extends Property {
setCurrentType(property.getCurrentType());
}
+ private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ // Restore getters array
+ getters = new MethodHandle[NOOF_TYPES];
+ }
+
private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) {
if (mh == null) {
return null;
@@ -360,6 +380,16 @@ public final class AccessorProperty extends Property {
}
@Override
+ void initMethodHandles(final Class<?> structure) {
+ if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) {
+ throw new IllegalArgumentException();
+ }
+ if (!isSpill()) {
+ initGetterSetter(structure);
+ }
+ }
+
+ @Override
public MethodHandle getGetter(final Class<?> type) {
final int i = getAccessorTypeIndex(type);
ensureObjectGetter();
diff --git a/src/jdk/nashorn/internal/runtime/CodeInstaller.java b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
index 28c9630e..579b6f3e 100644
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.runtime;
+import java.util.Map;
import jdk.nashorn.internal.codegen.ClassEmitter;
/**
@@ -52,7 +53,7 @@ public interface CodeInstaller<T> {
* @param bytecode bytecode
* @return the installed class
*/
- public Class<?> install(final String className, final byte[] bytecode);
+ public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants);
/**
* Verify generated bytecode before emission. This is called back from the
@@ -74,4 +75,13 @@ public interface CodeInstaller<T> {
* @return unique eval id
*/
public long getUniqueEvalId();
+
+ /**
+ * Store a compiled script for later reuse
+ * @param source the script source
+ * @param mainClassName the main class name
+ * @param classBytes map of class names to class bytes
+ * @param constants constants array
+ */
+ public void storeCompiledScript(Source source, String mainClassName, Map<String, byte[]> classBytes, Object[] constants);
}
diff --git a/src/jdk/nashorn/internal/runtime/CodeStore.java b/src/jdk/nashorn/internal/runtime/CodeStore.java
new file mode 100644
index 00000000..8f595999
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/CodeStore.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Base64;
+import java.util.Map;
+
+/**
+ * A code cache for persistent caching of compiled scripts.
+ */
+final class CodeStore {
+
+ private final File dir;
+ private final int minSize;
+
+ // Message digest to file name encoder
+ private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+
+ // Default minimum size for storing a compiled script class
+ private final static int DEFAULT_MIN_SIZE = 1000;
+
+ /**
+ * Constructor
+ * @param path directory to store code in
+ * @throws IOException
+ */
+ public CodeStore(final String path) throws IOException {
+ this(path, DEFAULT_MIN_SIZE);
+ }
+
+ /**
+ * Constructor
+ * @param path directory to store code in
+ * @param minSize minimum file size for caching scripts
+ * @throws IOException
+ */
+ public CodeStore(final String path, final int minSize) throws IOException {
+ this.dir = checkDirectory(path);
+ this.minSize = minSize;
+ }
+
+ private static File checkDirectory(final String path) throws IOException {
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
+ @Override
+ public File run() throws IOException {
+ final File dir = new File(path).getAbsoluteFile();
+ if (!dir.exists() && !dir.mkdirs()) {
+ throw new IOException("Could not create directory: " + dir);
+ } else if (!dir.isDirectory()) {
+ throw new IOException("Not a directory: " + dir);
+ } else if (!dir.canRead() || !dir.canWrite()) {
+ throw new IOException("Directory not readable or writable: " + dir);
+ }
+ return dir;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ }
+
+ /**
+ * Return a compiled script from the cache, or null if it isn't found.
+ *
+ * @param source the source
+ * @return the compiled script or null
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ public CompiledScript getScript(final Source source) throws IOException, ClassNotFoundException {
+ if (source.getLength() < minSize) {
+ return null;
+ }
+
+ final String digest = BASE64.encodeToString(source.getDigest());
+ final File file = new File(dir, digest);
+
+ try {
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<CompiledScript>() {
+ @Override
+ public CompiledScript run() throws IOException, ClassNotFoundException {
+ if (!file.exists()) {
+ return null;
+ }
+ try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
+ CompiledScript compiledScript = (CompiledScript) in.readObject();
+ compiledScript.setSource(source);
+ return compiledScript;
+ }
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ final Exception ex = e.getException();
+ if (ex instanceof IOException) {
+ throw (IOException) ex;
+ } else if (ex instanceof ClassNotFoundException) {
+ throw (ClassNotFoundException) ex;
+ }
+ throw (new RuntimeException(ex));
+ }
+ }
+
+ /**
+ * Store a compiled script in the cache.
+ *
+ * @param source the source
+ * @param mainClassName the main class name
+ * @param classBytes a map of class bytes
+ * @param constants the constants array
+ * @throws IOException
+ */
+ public void putScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants)
+ throws IOException {
+ if (source.getLength() < minSize) {
+ return;
+ }
+ for (final Object constant : constants) {
+ // Make sure all constant data is serializable
+ if (! (constant instanceof Serializable)) {
+ return;
+ }
+ }
+
+ final String digest = BASE64.encodeToString(source.getDigest());
+ final File file = new File(dir, digest);
+ final CompiledScript script = new CompiledScript(source, mainClassName, classBytes, constants);
+
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws IOException {
+ try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
+ out.writeObject(script);
+ }
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException) e.getException();
+ }
+ }
+}
+
diff --git a/src/jdk/nashorn/internal/runtime/CompiledScript.java b/src/jdk/nashorn/internal/runtime/CompiledScript.java
new file mode 100644
index 00000000..6bb8e9a0
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/CompiledScript.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Class representing a compiled script.
+ */
+final class CompiledScript implements Serializable {
+
+ /** Main class name. */
+ private final String mainClassName;
+
+ /** Map of class names to class bytes. */
+ private final Map<String, byte[]> classBytes;
+
+ /** Constants array. */
+ private final Object[] constants;
+
+ /** The source */
+ private transient Source source;
+
+ private static final long serialVersionUID = 2958227232195298340L;
+
+ /**
+ * Constructor.
+ *
+ * @param mainClassName main class name
+ * @param classBytes map of class names to class bytes
+ * @param constants constants array
+ */
+ CompiledScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) {
+ this.source = source;
+ this.mainClassName = mainClassName;
+ this.classBytes = classBytes;
+ this.constants = constants;
+ }
+
+ /**
+ * Returns the main class name.
+ * @return the main class name
+ */
+ public String getMainClassName() {
+ return mainClassName;
+ }
+
+ /**
+ * Returns a map of class names to class bytes.
+ * @return map of class bytes
+ */
+ public Map<String, byte[]> getClassBytes() {
+ return classBytes;
+ }
+
+ /**
+ * Returns the constants array.
+ * @return constants array
+ */
+ public Object[] getConstants() {
+ return constants;
+ }
+
+ /**
+ * Returns the source of this cached script.
+ * @return the source
+ */
+ public Source getSource() {
+ return source;
+ }
+
+ /**
+ * Sets the source of this cached script.
+ * @param source the source
+ */
+ void setSource(final Source source) {
+ this.source = source;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = mainClassName.hashCode();
+ hash = 31 * hash + classBytes.hashCode();
+ hash = 31 * hash + Arrays.hashCode(constants);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof CompiledScript)) {
+ return false;
+ }
+
+ final CompiledScript cs = (CompiledScript) obj;
+ return mainClassName.equals(cs.mainClassName)
+ && classBytes.equals(cs.classBytes)
+ && Arrays.equals(constants, cs.constants);
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java
index 86b5abd8..9f2c521d 100644
--- a/src/jdk/nashorn/internal/runtime/Context.java
+++ b/src/jdk/nashorn/internal/runtime/Context.java
@@ -25,17 +25,23 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.concurrent.atomic.AtomicLong;
import java.net.MalformedURLException;
@@ -46,7 +52,11 @@ import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassReader;
@@ -91,6 +101,11 @@ public final class Context {
*/
public static final String NASHORN_JAVA_REFLECTION = "nashorn.JavaReflection";
+ /**
+ * Permission to enable nashorn debug mode.
+ */
+ public static final String NASHORN_DEBUG_MODE = "nashorn.debugMode";
+
// nashorn load psuedo URL prefixes
private static final String LOAD_CLASSPATH = "classpath:";
private static final String LOAD_FX = "fx:";
@@ -126,8 +141,32 @@ public final class Context {
}
@Override
- public Class<?> install(final String className, final byte[] bytecode) {
- return loader.installClass(className, bytecode, codeSource);
+ public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants) {
+ Compiler.LOG.fine("Installing class ", className);
+
+ final String binaryName = Compiler.binaryName(className);
+ final Class<?> clazz = loader.installClass(binaryName, bytecode, codeSource);
+
+ try {
+ // Need doPrivileged because these fields are private
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ //use reflection to write source and constants table to installed classes
+ final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
+ final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
+ sourceField.setAccessible(true);
+ constantsField.setAccessible(true);
+ sourceField.set(null, source);
+ constantsField.set(null, constants);
+ return null;
+ }
+ });
+ } catch (final PrivilegedActionException e) {
+ throw new RuntimeException(e);
+ }
+
+ return clazz;
}
@Override
@@ -144,21 +183,39 @@ public final class Context {
public long getUniqueEvalId() {
return context.getUniqueEvalId();
}
+
+ @Override
+ public void storeCompiledScript(final Source source, final String mainClassName,
+ final Map<String, byte[]> classBytes, final Object[] constants) {
+ if (context.codeStore != null) {
+ try {
+ context.codeStore.putScript(source, mainClassName, classBytes, constants);
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
}
/** Is Context global debug mode enabled ? */
public static final boolean DEBUG = Options.getBooleanProperty("nashorn.debug");
- private static final ThreadLocal<ScriptObject> currentGlobal = new ThreadLocal<>();
+ private static final ThreadLocal<Global> currentGlobal = new ThreadLocal<>();
+
+ // in-memory cache for loaded classes
+ private ClassCache classCache;
+
+ // persistent code store
+ private CodeStore codeStore;
/**
* Get the current global scope
* @return the current global scope
*/
- public static ScriptObject getGlobal() {
+ public static Global getGlobal() {
// This class in a package.access protected package.
// Trusted code only can call this method.
- return getGlobalTrusted();
+ return currentGlobal.get();
}
/**
@@ -167,10 +224,19 @@ public final class Context {
*/
public static void setGlobal(final ScriptObject global) {
if (global != null && !(global instanceof Global)) {
- throw new IllegalArgumentException("global is not an instance of Global!");
+ throw new IllegalArgumentException("not a global!");
}
+ setGlobal((Global)global);
+ }
- setGlobalTrusted(global);
+ /**
+ * Set the current global scope
+ * @param global the global scope
+ */
+ public static void setGlobal(final Global global) {
+ // This class in a package.access protected package.
+ // Trusted code only can call this method.
+ currentGlobal.set(global);
}
/**
@@ -191,7 +257,7 @@ public final class Context {
* @return error writer of the current context
*/
public static PrintWriter getCurrentErr() {
- final ScriptObject global = getGlobalTrusted();
+ final ScriptObject global = getGlobal();
return (global != null)? global.getContext().getErr() : new PrintWriter(System.err);
}
@@ -344,6 +410,24 @@ public final class Context {
this.classPathLoader = null;
}
+ final int cacheSize = env._class_cache_size;
+ if (cacheSize > 0) {
+ classCache = new ClassCache(cacheSize);
+ }
+
+ if (env._persistent_cache) {
+ if (env._lazy_compilation || env._specialize_calls != null) {
+ getErr().println("Can not use persistent class caching with lazy compilation or call specialization.");
+ } else {
+ try {
+ final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
+ codeStore = new CodeStore(cacheDir);
+ } catch (IOException e) {
+ throw new RuntimeException("Error initializing code cache", e);
+ }
+ }
+ }
+
// print version info if asked.
if (env._version) {
getErr().println("nashorn " + Version.version());
@@ -391,7 +475,7 @@ public final class Context {
* @return the property map of the current global scope
*/
public static PropertyMap getGlobalMap() {
- return Context.getGlobalTrusted().getMap();
+ return Context.getGlobal().getMap();
}
/**
@@ -407,6 +491,39 @@ public final class Context {
}
/**
+ * Interface to represent compiled code that can be re-used across many
+ * global scope instances
+ */
+ public static interface MultiGlobalCompiledScript {
+ /**
+ * Obtain script function object for a specific global scope object.
+ *
+ * @param newGlobal global scope for which function object is obtained
+ * @return script function for script level expressions
+ */
+ public ScriptFunction getFunction(final Global newGlobal);
+ }
+
+ /**
+ * Compile a top level script.
+ *
+ * @param source the script source
+ * @return reusable compiled script across many global scopes.
+ */
+ public MultiGlobalCompiledScript compileScript(final Source source) {
+ final Class<?> clazz = compile(source, this.errors, this._strict);
+ final MethodHandle runMethodHandle = getRunScriptHandle(clazz);
+ final boolean strict = isStrict(clazz);
+
+ return new MultiGlobalCompiledScript() {
+ @Override
+ public ScriptFunction getFunction(final Global newGlobal) {
+ return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict);
+ }
+ };
+ }
+
+ /**
* Entry point for {@code eval}
*
* @param initialScope The scope of this eval call
@@ -419,9 +536,9 @@ public final class Context {
*/
public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
final String file = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
- final Source source = new Source(file, string);
+ final Source source = sourceFor(file, string);
final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
ScriptObject scope = initialScope;
@@ -453,7 +570,7 @@ public final class Context {
// in the caller's environment. A new environment is created!
if (strictFlag) {
// Create a new scope object
- final ScriptObject strictEvalScope = ((GlobalObject)global).newObject();
+ final ScriptObject strictEvalScope = global.newObject();
// bless it as a "scope"
strictEvalScope.setIsScope();
@@ -486,7 +603,7 @@ public final class Context {
public Source run() {
try {
final URL resURL = Context.class.getResource(resource);
- return (resURL != null)? new Source(srcStr, resURL) : null;
+ return (resURL != null)? sourceFor(srcStr, resURL) : null;
} catch (final IOException exp) {
return null;
}
@@ -518,7 +635,7 @@ public final class Context {
final String srcStr = (String)src;
if (srcStr.startsWith(LOAD_CLASSPATH)) {
URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
- source = (url != null)? new Source(url.toString(), url) : null;
+ source = (url != null)? sourceFor(url.toString(), url) : null;
} else {
final File file = new File(srcStr);
if (srcStr.indexOf(':') != -1) {
@@ -531,31 +648,31 @@ public final class Context {
} catch (final MalformedURLException e) {
url = file.toURI().toURL();
}
- source = new Source(url.toString(), url);
+ source = sourceFor(url.toString(), url);
}
} else if (file.isFile()) {
- source = new Source(srcStr, file);
+ source = sourceFor(srcStr, file);
}
}
} else if (src instanceof File && ((File)src).isFile()) {
final File file = (File)src;
- source = new Source(file.getName(), file);
+ source = sourceFor(file.getName(), file);
} else if (src instanceof URL) {
final URL url = (URL)src;
- source = new Source(url.toString(), url);
+ source = sourceFor(url.toString(), url);
} else if (src instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)src;
if (sobj.has("script") && sobj.has("name")) {
final String script = JSType.toString(sobj.get("script"));
final String name = JSType.toString(sobj.get("name"));
- source = new Source(name, script);
+ source = sourceFor(name, script);
}
} else if (src instanceof Map) {
final Map<?,?> map = (Map<?,?>)src;
if (map.containsKey("script") && map.containsKey("name")) {
final String script = JSType.toString(map.get("script"));
final String name = JSType.toString(map.get("name"));
- source = new Source(name, script);
+ source = sourceFor(name, script);
}
}
@@ -578,10 +695,10 @@ public final class Context {
* @throws IOException if source cannot be found or loaded
*/
public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
- final ScriptObject oldGlobal = getGlobalTrusted();
- final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
+ final Global oldGlobal = getGlobal();
+ final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
@Override
- public ScriptObject run() {
+ public Global run() {
try {
return newGlobal();
} catch (final RuntimeException e) {
@@ -594,17 +711,17 @@ public final class Context {
}, CREATE_GLOBAL_ACC_CTXT);
// initialize newly created Global instance
initGlobal(newGlobal);
- setGlobalTrusted(newGlobal);
+ setGlobal(newGlobal);
final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal);
- newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped), env._strict);
+ newGlobal.put("arguments", newGlobal.wrapAsObject(wrapped), env._strict);
try {
// wrap objects from newGlobal's world as mirrors - but if result
// is from oldGlobal's world, unwrap it!
return ScriptObjectMirror.unwrap(ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal), oldGlobal);
} finally {
- setGlobalTrusted(oldGlobal);
+ setGlobal(oldGlobal);
}
}
@@ -633,7 +750,7 @@ public final class Context {
* Checks that the given Class can be accessed from no permissions context.
*
* @param clazz Class object
- * @throw SecurityException if not accessible
+ * @throws SecurityException if not accessible
*/
public static void checkPackageAccess(final Class<?> clazz) {
final SecurityManager sm = System.getSecurityManager();
@@ -650,12 +767,12 @@ public final class Context {
* Checks that the given package name can be accessed from no permissions context.
*
* @param pkgName package name
- * @throw SecurityException if not accessible
+ * @throws SecurityException if not accessible
*/
public static void checkPackageAccess(final String pkgName) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkPackageAccess(sm, pkgName.endsWith(".")? pkgName : pkgName + ".");
+ checkPackageAccess(sm, pkgName.endsWith(".") ? pkgName : pkgName + ".");
}
}
@@ -779,7 +896,7 @@ public final class Context {
*
* @return the initialized global scope object.
*/
- public ScriptObject createGlobal() {
+ public Global createGlobal() {
return initGlobal(newGlobal());
}
@@ -787,7 +904,7 @@ public final class Context {
* Create a new uninitialized global scope object
* @return the global script object
*/
- public ScriptObject newGlobal() {
+ public Global newGlobal() {
return new Global(this);
}
@@ -797,20 +914,16 @@ public final class Context {
* @param global the global
* @return the initialized global scope object.
*/
- public ScriptObject initGlobal(final ScriptObject global) {
- if (! (global instanceof GlobalObject)) {
- throw new IllegalArgumentException("not a global object!");
- }
-
+ public Global initGlobal(final Global global) {
// Need only minimal global object, if we are just compiling.
if (!env._compile_only) {
- final ScriptObject oldGlobal = Context.getGlobalTrusted();
+ final Global oldGlobal = Context.getGlobal();
try {
- Context.setGlobalTrusted(global);
+ Context.setGlobal(global);
// initialize global scope with builtin global objects
- ((GlobalObject)global).initBuiltinObjects();
+ global.initBuiltinObjects();
} finally {
- Context.setGlobalTrusted(oldGlobal);
+ Context.setGlobal(oldGlobal);
}
}
@@ -818,30 +931,15 @@ public final class Context {
}
/**
- * Trusted variants - package-private
+ * Trusted variant - package-private
*/
/**
- * Return the current global scope
- * @return current global scope
- */
- static ScriptObject getGlobalTrusted() {
- return currentGlobal.get();
- }
-
- /**
- * Set the current global scope
- */
- static void setGlobalTrusted(ScriptObject global) {
- currentGlobal.set(global);
- }
-
- /**
* Return the current global's context
* @return current global's context
*/
static Context getContextTrusted() {
- return Context.getGlobalTrusted().getContext();
+ return ((ScriptObject)Context.getGlobal()).getContext();
}
/**
@@ -885,14 +983,8 @@ public final class Context {
return ScriptRuntime.apply(script, thiz);
}
- private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
- if (script == null) {
- return null;
- }
-
- // Get run method - the entry point to the script
- final MethodHandle runMethodHandle =
- MH.findStatic(
+ private static MethodHandle getRunScriptHandle(final Class<?> script) {
+ return MH.findStatic(
MethodHandles.lookup(),
script,
RUN_SCRIPT.symbolName(),
@@ -900,17 +992,27 @@ public final class Context {
Object.class,
ScriptFunction.class,
Object.class));
+ }
- boolean strict;
-
+ private static boolean isStrict(final Class<?> script) {
try {
- strict = script.getField(STRICT_MODE.symbolName()).getBoolean(null);
+ return script.getField(STRICT_MODE.symbolName()).getBoolean(null);
} catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
- strict = false;
+ return false;
+ }
+ }
+
+ private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
+ if (script == null) {
+ return null;
}
+ // Get run method - the entry point to the script
+ final MethodHandle runMethodHandle = getRunScriptHandle(script);
+ boolean strict = isStrict(script);
+
// Package as a JavaScript function and pass function back to shell.
- return ((GlobalObject)Context.getGlobalTrusted()).newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
+ return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
}
private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
@@ -921,29 +1023,38 @@ public final class Context {
// start with no errors, no warnings.
errMan.reset();
- GlobalObject global = null;
- Class<?> script;
+ Class<?> script = findCachedClass(source);
+ if (script != null) {
+ Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
+ return script;
+ }
+
+ CompiledScript compiledScript = null;
+ FunctionNode functionNode = null;
- if (env._class_cache_size > 0) {
- global = (GlobalObject)Context.getGlobalTrusted();
- script = global.findCachedClass(source);
- if (script != null) {
- Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
- return script;
+ if (!env._parse_only && codeStore != null) {
+ try {
+ compiledScript = codeStore.getScript(source);
+ } catch (IOException | ClassNotFoundException e) {
+ Compiler.LOG.warning("Error loading ", source, " from cache: ", e);
+ // Fall back to normal compilation
}
}
- final FunctionNode functionNode = new Parser(env, source, errMan, strict).parse();
- if (errors.hasErrors()) {
- return null;
- }
+ if (compiledScript == null) {
+ functionNode = new Parser(env, source, errMan, strict).parse();
- if (env._print_ast) {
- getErr().println(new ASTWriter(functionNode));
- }
+ if (errors.hasErrors()) {
+ return null;
+ }
+
+ if (env._print_ast) {
+ getErr().println(new ASTWriter(functionNode));
+ }
- if (env._print_parse) {
- getErr().println(new PrintVisitor(functionNode));
+ if (env._print_parse) {
+ getErr().println(new PrintVisitor(functionNode));
+ }
}
if (env._parse_only) {
@@ -952,18 +1063,18 @@ public final class Context {
final URL url = source.getURL();
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
- final CodeSource cs = url == null ? null : new CodeSource(url, (CodeSigner[])null);
+ final CodeSource cs = new CodeSource(url, (CodeSigner[])null);
final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
- final Compiler compiler = new Compiler(installer, strict);
-
- final FunctionNode newFunctionNode = compiler.compile(functionNode);
- script = compiler.install(newFunctionNode);
-
- if (global != null) {
- global.cacheClass(source, script);
+ if (functionNode != null) {
+ final Compiler compiler = new Compiler(installer, strict);
+ final FunctionNode newFunctionNode = compiler.compile(functionNode);
+ script = compiler.install(newFunctionNode);
+ } else {
+ script = install(compiledScript, installer);
}
+ cacheClass(source, script);
return script;
}
@@ -984,4 +1095,96 @@ public final class Context {
private long getUniqueScriptId() {
return uniqueScriptId.getAndIncrement();
}
+
+
+ /**
+ * Install a previously compiled class from the code cache.
+ *
+ * @param compiledScript cached script containing class bytes and constants
+ * @return main script class
+ */
+ private Class<?> install(final CompiledScript compiledScript, final CodeInstaller<ScriptEnvironment> installer) {
+
+ final Map<String, Class<?>> installedClasses = new HashMap<>();
+ final Source source = compiledScript.getSource();
+ final Object[] constants = compiledScript.getConstants();
+ final String rootClassName = compiledScript.getMainClassName();
+ final byte[] rootByteCode = compiledScript.getClassBytes().get(rootClassName);
+ final Class<?> rootClass = installer.install(rootClassName, rootByteCode, source, constants);
+
+ installedClasses.put(rootClassName, rootClass);
+
+ for (final Map.Entry<String, byte[]> entry : compiledScript.getClassBytes().entrySet()) {
+ final String className = entry.getKey();
+ if (className.equals(rootClassName)) {
+ continue;
+ }
+ final byte[] code = entry.getValue();
+
+ installedClasses.put(className, installer.install(className, code, source, constants));
+ }
+ for (Object constant : constants) {
+ if (constant instanceof RecompilableScriptFunctionData) {
+ ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source);
+ }
+ }
+
+ return rootClass;
+ }
+
+ /**
+ * Cache for compiled script classes.
+ */
+ @SuppressWarnings("serial")
+ private static class ClassCache extends LinkedHashMap<Source, ClassReference> {
+ private final int size;
+ private final ReferenceQueue<Class<?>> queue;
+
+ ClassCache(int size) {
+ super(size, 0.75f, true);
+ this.size = size;
+ this.queue = new ReferenceQueue<>();
+ }
+
+ void cache(final Source source, final Class<?> clazz) {
+ put(source, new ClassReference(clazz, queue, source));
+ }
+
+ @Override
+ protected boolean removeEldestEntry(final Map.Entry<Source, ClassReference> eldest) {
+ return size() > size;
+ }
+
+ @Override
+ public ClassReference get(Object key) {
+ for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
+ remove(ref.source);
+ }
+ return super.get(key);
+ }
+
+ }
+
+ private static class ClassReference extends SoftReference<Class<?>> {
+ private final Source source;
+
+ ClassReference(final Class<?> clazz, final ReferenceQueue<Class<?>> queue, final Source source) {
+ super(clazz, queue);
+ this.source = source;
+ }
+ }
+
+ // Class cache management
+ private Class<?> findCachedClass(final Source source) {
+ ClassReference ref = classCache == null ? null : classCache.get(source);
+ return ref != null ? ref.get() : null;
+ }
+
+ private void cacheClass(final Source source, final Class<?> clazz) {
+ if (classCache != null) {
+ classCache.cache(source, clazz);
+ }
+ }
+
+
}
diff --git a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
index c288a963..261bc020 100644
--- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
+++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
@@ -75,7 +75,7 @@ final class DebuggerSupport {
* @return context global.
*/
static Object getGlobal() {
- return Context.getGlobalTrusted();
+ return Context.getGlobal();
}
/**
@@ -87,7 +87,7 @@ final class DebuggerSupport {
* @return Result of eval as string, or, an exception or null depending on returnException.
*/
static Object eval(final ScriptObject scope, final Object self, final String string, final boolean returnException) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final ScriptObject global = Context.getGlobal();
final ScriptObject initialScope = scope != null ? scope : global;
final Object callThis = self != null ? self : global;
final Context context = global.getContext();
diff --git a/src/jdk/nashorn/internal/runtime/ECMAErrors.java b/src/jdk/nashorn/internal/runtime/ECMAErrors.java
index 0ff843a4..affba497 100644
--- a/src/jdk/nashorn/internal/runtime/ECMAErrors.java
+++ b/src/jdk/nashorn/internal/runtime/ECMAErrors.java
@@ -30,6 +30,8 @@ import java.util.Locale;
import java.util.ResourceBundle;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.scripts.JS;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.objects.Global;
/**
* Helper class to throw various standard "ECMA error" exceptions such as Error, ReferenceError, TypeError etc.
@@ -65,7 +67,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException asEcmaException(final ParserException e) {
- return asEcmaException(Context.getGlobalTrusted(), e);
+ return asEcmaException(Context.getGlobal(), e);
}
/**
@@ -77,11 +79,11 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException asEcmaException(final ScriptObject global, final ParserException e) {
+ public static ECMAException asEcmaException(final Global global, final ParserException e) {
final JSErrorType errorType = e.getErrorType();
assert errorType != null : "error type for " + e + " was null";
- final GlobalObject globalObj = (GlobalObject)global;
+ final Global globalObj = global;
final String msg = e.getMessage();
// translate to ECMAScript Error object using error type
@@ -115,7 +117,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException syntaxError(final String msgId, final String... args) {
- return syntaxError(Context.getGlobalTrusted(), msgId, args);
+ return syntaxError(Context.getGlobal(), msgId, args);
}
/**
@@ -127,7 +129,7 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException syntaxError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException syntaxError(final Global global, final String msgId, final String... args) {
return syntaxError(global, null, msgId, args);
}
@@ -141,7 +143,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException syntaxError(final Throwable cause, final String msgId, final String... args) {
- return syntaxError(Context.getGlobalTrusted(), cause, msgId, args);
+ return syntaxError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -154,9 +156,9 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException syntaxError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException syntaxError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("syntax.error." + msgId, args);
- return error(((GlobalObject)global).newSyntaxError(msg), cause);
+ return error(global.newSyntaxError(msg), cause);
}
/**
@@ -168,7 +170,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException typeError(final String msgId, final String... args) {
- return typeError(Context.getGlobalTrusted(), msgId, args);
+ return typeError(Context.getGlobal(), msgId, args);
}
/**
@@ -180,7 +182,7 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException typeError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException typeError(final Global global, final String msgId, final String... args) {
return typeError(global, null, msgId, args);
}
@@ -194,7 +196,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException typeError(final Throwable cause, final String msgId, final String... args) {
- return typeError(Context.getGlobalTrusted(), cause, msgId, args);
+ return typeError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -207,9 +209,9 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException typeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException typeError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("type.error." + msgId, args);
- return error(((GlobalObject)global).newTypeError(msg), cause);
+ return error(global.newTypeError(msg), cause);
}
/**
@@ -221,7 +223,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException rangeError(final String msgId, final String... args) {
- return rangeError(Context.getGlobalTrusted(), msgId, args);
+ return rangeError(Context.getGlobal(), msgId, args);
}
/**
@@ -233,7 +235,7 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException rangeError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException rangeError(final Global global, final String msgId, final String... args) {
return rangeError(global, null, msgId, args);
}
@@ -247,7 +249,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException rangeError(final Throwable cause, final String msgId, final String... args) {
- return rangeError(Context.getGlobalTrusted(), cause, msgId, args);
+ return rangeError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -260,9 +262,9 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException rangeError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException rangeError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("range.error." + msgId, args);
- return error(((GlobalObject)global).newRangeError(msg), cause);
+ return error(global.newRangeError(msg), cause);
}
/**
@@ -274,7 +276,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException referenceError(final String msgId, final String... args) {
- return referenceError(Context.getGlobalTrusted(), msgId, args);
+ return referenceError(Context.getGlobal(), msgId, args);
}
/**
@@ -286,7 +288,7 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException referenceError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException referenceError(final Global global, final String msgId, final String... args) {
return referenceError(global, null, msgId, args);
}
@@ -300,7 +302,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException referenceError(final Throwable cause, final String msgId, final String... args) {
- return referenceError(Context.getGlobalTrusted(), cause, msgId, args);
+ return referenceError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -313,9 +315,9 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException referenceError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException referenceError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("reference.error." + msgId, args);
- return error(((GlobalObject)global).newReferenceError(msg), cause);
+ return error(global.newReferenceError(msg), cause);
}
/**
@@ -327,7 +329,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException uriError(final String msgId, final String... args) {
- return uriError(Context.getGlobalTrusted(), msgId, args);
+ return uriError(Context.getGlobal(), msgId, args);
}
/**
@@ -339,7 +341,7 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException uriError(final ScriptObject global, final String msgId, final String... args) {
+ public static ECMAException uriError(final Global global, final String msgId, final String... args) {
return uriError(global, null, msgId, args);
}
@@ -353,7 +355,7 @@ public final class ECMAErrors {
* @return the resulting {@link ECMAException}
*/
public static ECMAException uriError(final Throwable cause, final String msgId, final String... args) {
- return uriError(Context.getGlobalTrusted(), cause, msgId, args);
+ return uriError(Context.getGlobal(), cause, msgId, args);
}
/**
@@ -366,9 +368,9 @@ public final class ECMAErrors {
*
* @return the resulting {@link ECMAException}
*/
- public static ECMAException uriError(final ScriptObject global, final Throwable cause, final String msgId, final String... args) {
+ public static ECMAException uriError(final Global global, final Throwable cause, final String msgId, final String... args) {
final String msg = getMessage("uri.error." + msgId, args);
- return error(((GlobalObject)global).newURIError(msg), cause);
+ return error(global.newURIError(msg), cause);
}
/**
@@ -401,7 +403,7 @@ public final class ECMAErrors {
final String className = frame.getClassName();
// Look for script package in class name (into which compiler puts generated code)
- if (className.startsWith(scriptPackage)) {
+ if (className.startsWith(scriptPackage) && !frame.getMethodName().startsWith(CompilerConstants.INTERNAL_METHOD_PREFIX)) {
final String source = frame.getFileName();
/*
* Make sure that it is not some Java code that Nashorn has in that package!
diff --git a/src/jdk/nashorn/internal/runtime/ECMAException.java b/src/jdk/nashorn/internal/runtime/ECMAException.java
index a32e721c..c900963d 100644
--- a/src/jdk/nashorn/internal/runtime/ECMAException.java
+++ b/src/jdk/nashorn/internal/runtime/ECMAException.java
@@ -25,7 +25,7 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualField;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -44,9 +44,9 @@ import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess;
@SuppressWarnings("serial")
public final class ECMAException extends NashornException {
/**
- * Method handle pointing to the constructor {@link ECMAException#ECMAException(Object, String, int, int)},
+ * Method handle pointing to the constructor {@link ECMAException#create(Object, String, int, int)},
*/
- public static final Call THROW_INIT = constructorNoLookup(ECMAException.class, Object.class, String.class, int.class, int.class);
+ public static final Call CREATE = staticCallNoLookup(ECMAException.class, "create", ECMAException.class, Object.class, String.class, int.class, int.class);
/** Field handle to the{@link ECMAException#thrown} field, so that it can be accessed from generated code */
public static final FieldAccess THROWN = virtualField(ECMAException.class, "thrown", Object.class);
@@ -57,23 +57,21 @@ public final class ECMAException extends NashornException {
public final Object thrown;
/**
- * Constructor. This is called from generated code to implement the {@code throw}
- * instruction from generated script code
+ * Constructor. Called from the factory method 'create'.
*
* @param thrown object to be thrown
* @param fileName script file name
* @param line line number of throw
* @param column column number of throw
*/
- public ECMAException(final Object thrown, final String fileName, final int line, final int column) {
+ private ECMAException(final Object thrown, final String fileName, final int line, final int column) {
super(ScriptRuntime.safeToString(thrown), asThrowable(thrown), fileName, line, column);
this.thrown = thrown;
setExceptionToThrown();
}
/**
- * Constructor. This is called from runtime code in Nashorn to throw things like
- * type errors.
+ * Constructor. This is called from the runtime code.
*
* @param thrown object to be thrown
* @param cause Java exception that triggered this throw
@@ -85,9 +83,39 @@ public final class ECMAException extends NashornException {
}
/**
+ * Factory method to retrieve the underlying exception or create an exception.
+ * This method is called from the generated code.
+ *
+ * @param thrown object to be thrown
+ * @param fileName script file name
+ * @param line line number of throw
+ * @param column column number of throw
+ * @return ECMAException object
+ */
+ public static ECMAException create(final Object thrown, final String fileName, final int line, final int column) {
+ // If thrown object is an Error or sub-object like TypeError, then
+ // an ECMAException object has been already initialized at constructor.
+ if (thrown instanceof ScriptObject) {
+ ScriptObject sobj = (ScriptObject)thrown;
+ Object exception = getException(sobj);
+ if (exception instanceof ECMAException) {
+ // copy over file name, line number and column number.
+ final ECMAException ee = (ECMAException)exception;
+ ee.setFileName(fileName);
+ ee.setLineNumber(line);
+ ee.setColumnNumber(column);
+ return ee;
+ }
+ }
+
+ return new ECMAException(thrown, fileName, line, column);
+ }
+
+ /**
* Get the thrown object
* @return thrown object
*/
+ @Override
public Object getThrown() {
return thrown;
}
@@ -256,6 +284,8 @@ public final class ECMAException extends NashornException {
final ScriptObject sobj = (ScriptObject)thrown;
if (!sobj.has(EXCEPTION_PROPERTY)) {
sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
+ } else {
+ sobj.set(EXCEPTION_PROPERTY, this, false);
}
}
}
diff --git a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index c7a410ea..f16cf41c 100644
--- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -38,31 +38,27 @@ final class FinalScriptFunctionData extends ScriptFunctionData {
/**
* Constructor - used for bind
*
- * @param name name
- * @param arity arity
- * @param functions precompiled code
- * @param isStrict strict
- * @param isBuiltin builtin
- * @param isConstructor constructor
+ * @param name name
+ * @param arity arity
+ * @param functions precompiled code
+ * @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, int arity, CompiledFunctions functions, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- super(name, arity, isStrict, isBuiltin, isConstructor);
+ FinalScriptFunctionData(final String name, final int arity, final CompiledFunctions functions, final int flags) {
+ super(name, arity, flags);
code.addAll(functions);
}
/**
- * Constructor - used from ScriptFunction. This assumes that we have code alraedy for the
+ * Constructor - used from ScriptFunction. This assumes that we have code already for the
* method (typically a native method) and possibly specializations.
*
- * @param name name
- * @param mh method handle for generic version of method
- * @param specs specializations
- * @param isStrict strict
- * @param isBuiltin builtin
- * @param isConstructor constructor
+ * @param name name
+ * @param mh method handle for generic version of method
+ * @param specs specializations
+ * @param flags {@link ScriptFunctionData} flags
*/
- FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- super(name, arity(mh), isStrict, isBuiltin, isConstructor);
+ FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) {
+ super(name, arity(mh), flags);
addInvoker(mh);
if (specs != null) {
diff --git a/src/jdk/nashorn/internal/runtime/FindProperty.java b/src/jdk/nashorn/internal/runtime/FindProperty.java
index c14accb7..87a8c748 100644
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java
+++ b/src/jdk/nashorn/internal/runtime/FindProperty.java
@@ -112,7 +112,7 @@ public final class FindProperty {
return property != null && property.hasGetterFunction(prototype) ? self : prototype;
}
- /**
+ /**
* Return the appropriate receiver for a setter.
* @return appropriate receiver
*/
@@ -172,5 +172,20 @@ public final class FindProperty {
property.setObjectValue(getSetterReceiver(), getOwner(), value, strict);
}
+ /**
+ * Get the number of objects in the prototype chain between the {@code self} and the
+ * {@code owner} objects.
+ * @return the prototype chain length
+ */
+ int getProtoChainLength() {
+ assert self != null;
+ int length = 0;
+ for (ScriptObject obj = self; obj != prototype; obj = obj.getProto()) {
+ assert !(obj instanceof WithObject);
+ ++length;
+ }
+ return length;
+ }
+
}
diff --git a/src/jdk/nashorn/internal/runtime/GlobalObject.java b/src/jdk/nashorn/internal/runtime/GlobalObject.java
deleted file mode 100644
index 3779f3bd..00000000
--- a/src/jdk/nashorn/internal/runtime/GlobalObject.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.util.concurrent.Callable;
-import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.LinkRequest;
-import jdk.nashorn.internal.runtime.linker.InvokeByName;
-
-/**
- * Runtime interface to the global scope objects.
- */
-
-public interface GlobalObject {
- /**
- * Is this global of the given Context?
- * @param ctxt the context
- * @return true if this global belongs to the given Context
- */
- public boolean isOfContext(final Context ctxt);
-
- /**
- * Does this global belong to a strict Context?
- * @return true if this global belongs to a strict Context
- */
- public boolean isStrictContext();
-
- /**
- * Initialize standard builtin objects like "Object", "Array", "Function" etc.
- * as well as our extension builtin objects like "Java", "JSAdapter" as properties
- * of the global scope object.
- */
- public void initBuiltinObjects();
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newScriptFunction(String, MethodHandle, ScriptObject, boolean)}
- *
- * @param name function name
- * @param handle invocation handle for function
- * @param scope the scope
- * @param strict are we in strict mode
- *
- * @return new script function
- */
- public ScriptFunction newScriptFunction(String name, MethodHandle handle, ScriptObject scope, boolean strict);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#wrapAsObject(Object)}
- *
- * @param obj object to wrap
- * @return wrapped object
- */
- public Object wrapAsObject(Object obj);
-
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#primitiveLookup(LinkRequest, Object)}
- *
- * @param request the link request for the dynamic call site.
- * @param self self reference
- *
- * @return guarded invocation
- */
- public GuardedInvocation primitiveLookup(LinkRequest request, Object self);
-
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newObject()}
- *
- * @return the new ScriptObject
- */
- public ScriptObject newObject();
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#isError(ScriptObject)}
- *
- * @param sobj to check if it is an error object
- * @return true if error object
- */
- public boolean isError(ScriptObject sobj);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the error
- */
- public ScriptObject newError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newEvalError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the eval error
- */
- public ScriptObject newEvalError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newRangeError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the range error
- */
- public ScriptObject newRangeError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newReferenceError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the reference error
- */
- public ScriptObject newReferenceError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newSyntaxError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the syntax error
- */
- public ScriptObject newSyntaxError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newTypeError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the type error
- */
- public ScriptObject newTypeError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newURIError(String)}
- *
- * @param msg the error message
- *
- * @return the new ScriptObject representing the URI error
- */
- public ScriptObject newURIError(String msg);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newGenericDescriptor(boolean, boolean)}
- *
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newGenericDescriptor(boolean configurable, boolean enumerable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newDataDescriptor(Object, boolean, boolean, boolean)}
- *
- * @param value data value
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- * @param writable is the described property writable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newDataDescriptor(Object value, boolean configurable, boolean enumerable, boolean writable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#newAccessorDescriptor(Object, Object, boolean, boolean)}
- *
- * @param get property getter, or null if none
- * @param set property setter, or null if none
- * @param configurable is the described property configurable
- * @param enumerable is the described property enumerable
- *
- * @return property descriptor
- */
- public PropertyDescriptor newAccessorDescriptor(Object get, Object set, boolean configurable, boolean enumerable);
-
- /**
- * Wrapper for {@link jdk.nashorn.internal.objects.Global#getDefaultValue(ScriptObject, Class)}
- *
- * @param sobj script object
- * @param typeHint type hint
- *
- * @return default value
- */
- public Object getDefaultValue(ScriptObject sobj, Class<?> typeHint);
-
- /**
- * Find the compiled Class for the given script source, if available
- *
- * @param source Source object of the script
- * @return compiled Class object or null
- */
- public Class<?> findCachedClass(Source source);
-
- /**
- * Put the Source associated Class object in the Source-to-Class cache
- *
- * @param source Source of the script
- * @param clazz compiled Class object for the source
- */
- public void cacheClass(Source source, Class<?> clazz);
-
- /**
- * Get cached InvokeByName object for the given key
- * @param key key to be associated with InvokeByName object
- * @param creator if InvokeByName is absent 'creator' is called to make one (lazy init)
- * @return InvokeByName object associated with the key.
- */
- public InvokeByName getInvokeByName(final Object key, final Callable<InvokeByName> creator);
-
- /**
- * Get cached dynamic method handle for the given key
- * @param key key to be associated with dynamic method handle
- * @param creator if method handle is absent 'creator' is called to make one (lazy init)
- * @return dynamic method handle associated with the key.
- */
- public MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator);
-}
diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index 73552cb1..ab1de42f 100644
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -33,11 +33,14 @@ import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.JSONParser;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
/**
* Utilities used by "JSON" object implementation.
*/
@@ -47,7 +50,7 @@ public final class JSONFunctions {
private static final Object REVIVER_INVOKER = new Object();
private static MethodHandle getREVIVER_INVOKER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(REVIVER_INVOKER,
+ return Context.getGlobal().getDynamicInvoker(REVIVER_INVOKER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
@@ -76,9 +79,7 @@ public final class JSONFunctions {
*/
public static Object parse(final Object text, final Object reviver) {
final String str = JSType.toString(text);
- final JSONParser parser = new JSONParser(
- new Source("<json>", str),
- new Context.ThrowErrorManager());
+ final JSONParser parser = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager());
Node node;
@@ -88,7 +89,7 @@ public final class JSONFunctions {
throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
}
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
Object unfiltered = convertNode(global, node);
return applyReviver(global, unfiltered, reviver);
}
@@ -98,10 +99,9 @@ public final class JSONFunctions {
// parse helpers
// apply 'reviver' function if available
- private static Object applyReviver(final ScriptObject global, final Object unfiltered, final Object reviver) {
+ private static Object applyReviver(final Global global, final Object unfiltered, final Object reviver) {
if (reviver instanceof ScriptFunction) {
- assert global instanceof GlobalObject;
- final ScriptObject root = ((GlobalObject)global).newObject();
+ final ScriptObject root = global.newObject();
root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
return walk(root, "", (ScriptFunction)reviver);
}
@@ -138,8 +138,8 @@ public final class JSONFunctions {
}
// Converts IR node to runtime value
- private static Object convertNode(final ScriptObject global, final Node node) {
- assert global instanceof GlobalObject;
+ private static Object convertNode(final Global global, final Node node) {
+ assert global instanceof Global;
if (node instanceof LiteralNode) {
// check for array literal
@@ -157,7 +157,7 @@ public final class JSONFunctions {
for (final Node elem : elements) {
values[index++] = JSType.toNumber(convertNode(global, elem));
}
- return ((GlobalObject)global).wrapAsObject(values);
+ return global.wrapAsObject(values);
}
final Object[] values = new Object[elements.length];
@@ -167,14 +167,14 @@ public final class JSONFunctions {
values[index++] = convertNode(global, elem);
}
- return ((GlobalObject)global).wrapAsObject(values);
+ return global.wrapAsObject(values);
}
return ((LiteralNode<?>)node).getValue();
} else if (node instanceof ObjectNode) {
final ObjectNode objNode = (ObjectNode) node;
- final ScriptObject object = ((GlobalObject)global).newObject();
+ final ScriptObject object = global.newObject();
for (final PropertyNode pNode: objNode.getElements()) {
final Node valueNode = pNode.getValue();
diff --git a/src/jdk/nashorn/internal/runtime/JSType.java b/src/jdk/nashorn/internal/runtime/JSType.java
index 54130196..11cecbfe 100644
--- a/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/src/jdk/nashorn/internal/runtime/JSType.java
@@ -36,6 +36,7 @@ import java.util.List;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Lexer;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -437,7 +438,9 @@ public enum JSType {
// encode integer part from least significant digit, then reverse
do {
- sb.append(chars.charAt((int) (intPart % radix)));
+ final double remainder = intPart % radix;
+ sb.append(chars.charAt((int) remainder));
+ intPart -= remainder;
intPart /= radix;
} while (intPart >= 1.0);
@@ -852,7 +855,7 @@ public enum JSType {
* @return the wrapped object
*/
public static Object toScriptObject(final Object obj) {
- return toScriptObject(Context.getGlobalTrusted(), obj);
+ return toScriptObject(Context.getGlobal(), obj);
}
/**
@@ -865,7 +868,7 @@ public enum JSType {
*
* @return the wrapped object
*/
- public static Object toScriptObject(final ScriptObject global, final Object obj) {
+ public static Object toScriptObject(final Global global, final Object obj) {
if (nullOrUndefined(obj)) {
throw typeError(global, "not.an.object", ScriptRuntime.safeToString(obj));
}
@@ -874,7 +877,7 @@ public enum JSType {
return obj;
}
- return ((GlobalObject)global).wrapAsObject(obj);
+ return global.wrapAsObject(obj);
}
/**
@@ -984,7 +987,7 @@ public enum JSType {
if (obj instanceof ScriptObject) {
if (safe) {
final ScriptObject sobj = (ScriptObject)obj;
- final GlobalObject gobj = (GlobalObject)Context.getGlobalTrusted();
+ final Global gobj = Context.getGlobal();
return gobj.isError(sobj) ?
ECMAException.safeToString(sobj) :
sobj.safeToString();
diff --git a/src/jdk/nashorn/internal/runtime/ListAdapter.java b/src/jdk/nashorn/internal/runtime/ListAdapter.java
index 26c22c39..9a3408fb 100644
--- a/src/jdk/nashorn/internal/runtime/ListAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -34,6 +34,7 @@ import java.util.RandomAccess;
import java.util.concurrent.Callable;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.InvokeByName;
@@ -54,7 +55,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
// These add to the back and front of the list
private static final Object PUSH = new Object();
private static InvokeByName getPUSH() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(PUSH,
+ return Context.getGlobal().getInvokeByName(PUSH,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -65,7 +66,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
private static final Object UNSHIFT = new Object();
private static InvokeByName getUNSHIFT() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(UNSHIFT,
+ return Context.getGlobal().getInvokeByName(UNSHIFT,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -77,7 +78,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
// These remove from the back and front of the list
private static final Object POP = new Object();
private static InvokeByName getPOP() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(POP,
+ return Context.getGlobal().getInvokeByName(POP,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -88,7 +89,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
private static final Object SHIFT = new Object();
private static InvokeByName getSHIFT() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SHIFT,
+ return Context.getGlobal().getInvokeByName(SHIFT,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -100,7 +101,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
// These insert and remove in the middle of the list
private static final Object SPLICE_ADD = new Object();
private static InvokeByName getSPLICE_ADD() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_ADD,
+ return Context.getGlobal().getInvokeByName(SPLICE_ADD,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
@@ -111,7 +112,7 @@ public abstract class ListAdapter extends AbstractList<Object> implements Random
private static final Object SPLICE_REMOVE = new Object();
private static InvokeByName getSPLICE_REMOVE() {
- return ((GlobalObject)Context.getGlobal()).getInvokeByName(SPLICE_REMOVE,
+ return Context.getGlobal().getInvokeByName(SPLICE_REMOVE,
new Callable<InvokeByName>() {
@Override
public InvokeByName call() {
diff --git a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index 534d495c..fbca1c34 100644
--- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -35,7 +35,6 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.Guards;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
-import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -52,7 +51,7 @@ import jdk.nashorn.internal.objects.annotations.Function;
* var ArrayList = java.util.ArrayList
* var list = new ArrayList
* </pre>
- * You can also use {@link NativeJava#type(Object, Object)} to access Java classes. These two statements are mostly
+ * You can also use {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)} to access Java classes. These two statements are mostly
* equivalent:
* <pre>
* var listType1 = java.util.ArrayList
@@ -198,8 +197,26 @@ public final class NativeJavaPackage extends ScriptObject {
@Override
public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) {
final String propertyName = desc.getNameToken(2);
- final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
+ createProperty(propertyName);
+ return super.lookup(desc, request);
+ }
+
+ @Override
+ protected Object invokeNoSuchProperty(final String name) {
+ return createProperty(name);
+ }
+
+ @Override
+ public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+ return noSuchProperty(desc, request);
+ }
+
+ private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+ return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
+ }
+ private Object createProperty(final String propertyName) {
+ final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
final Context context = Context.getContextTrusted();
Class<?> javaClass = null;
@@ -209,21 +226,14 @@ public final class NativeJavaPackage extends ScriptObject {
//ignored
}
+ final Object propertyValue;
if (javaClass == null) {
- set(propertyName, new NativeJavaPackage(fullName, getProto()), false);
+ propertyValue = new NativeJavaPackage(fullName, getProto());
} else {
- set(propertyName, StaticClass.forClass(javaClass), false);
+ propertyValue = StaticClass.forClass(javaClass);
}
- return super.lookup(desc, request);
- }
-
- @Override
- public GuardedInvocation noSuchMethod(final CallSiteDescriptor desc, final LinkRequest request) {
- return noSuchProperty(desc, request);
- }
-
- private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
- return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
+ set(propertyName, propertyValue, false);
+ return propertyValue;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/ParserException.java b/src/jdk/nashorn/internal/runtime/ParserException.java
index 2424bc3f..5137d596 100644
--- a/src/jdk/nashorn/internal/runtime/ParserException.java
+++ b/src/jdk/nashorn/internal/runtime/ParserException.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import jdk.nashorn.api.scripting.NashornException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Token;
/**
@@ -110,7 +111,7 @@ public final class ParserException extends NashornException {
* Throw this {@code ParserException} as one of the 7 native JavaScript errors
* @param global global scope object
*/
- public void throwAsEcmaException(final ScriptObject global) {
+ public void throwAsEcmaException(final Global global) {
throw ECMAErrors.asEcmaException(global, this);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/Property.java b/src/jdk/nashorn/internal/runtime/Property.java
index d1dbe2ad..b3f1e0af 100644
--- a/src/jdk/nashorn/internal/runtime/Property.java
+++ b/src/jdk/nashorn/internal/runtime/Property.java
@@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
+import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.util.Objects;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -43,7 +44,7 @@ import jdk.nashorn.internal.codegen.types.Type;
* @see AccessorProperty
* @see UserAccessorProperty
*/
-public abstract class Property {
+public abstract class Property implements Serializable {
/*
* ECMA 8.6.1 Property Attributes
*
@@ -84,9 +85,13 @@ public abstract class Property {
/** Can this property be undefined? */
public static final int CAN_BE_UNDEFINED = 1 << 8;
- /* Is this a function declaration property ? */
+ /** Is this a function declaration property ? */
public static final int IS_FUNCTION_DECLARATION = 1 << 9;
+ /** Is this property bound to a receiver? This means get/set operations will be delegated to
+ * a statically defined object instead of the object passed as callsite parameter. */
+ public static final int IS_BOUND = 1 << 10;
+
/** Property key. */
private final String key;
@@ -96,6 +101,8 @@ public abstract class Property {
/** Property field number or spill slot. */
private final int slot;
+ private static final long serialVersionUID = 2099814273074501176L;
+
/**
* Constructor
*
@@ -252,6 +259,16 @@ public abstract class Property {
}
/**
+ * Is this property bound to a receiver? If this method returns {@code true} get and set operations
+ * will be delegated to a statically bound object instead of the object passed as parameter.
+ *
+ * @return true if this is a bound property
+ */
+ public boolean isBound() {
+ return (flags & IS_BOUND) == IS_BOUND;
+ }
+
+ /**
* Does this property use any slots in the spill array described in
* {@link Property#isSpill}? In that case how many. Currently a property
* only uses max one spill slot, but this may change in future representations
@@ -344,6 +361,13 @@ public abstract class Property {
public abstract MethodHandle getGetter(final Class<?> type);
/**
+ * Hook to initialize method handles after deserialization.
+ *
+ * @param structure the structure class
+ */
+ abstract void initMethodHandles(final Class<?> structure);
+
+ /**
* Get the key for this property. This key is an ordinary string. The "name".
* @return key for property
*/
diff --git a/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java b/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
index 49a7a9d6..f36bd45e 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
@@ -151,5 +151,12 @@ public interface PropertyDescriptor {
* @return true if property exists in implementor
*/
public boolean has(Object key);
+
+ /**
+ * Check existence and compare attributes of descriptors.
+ *
+ * @return true if every field of this desc exists in otherDesc and has the same value.
+ */
+ public boolean hasAndEquals(PropertyDescriptor otherDesc);
}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListener.java b/src/jdk/nashorn/internal/runtime/PropertyListener.java
deleted file mode 100644
index 307d58b4..00000000
--- a/src/jdk/nashorn/internal/runtime/PropertyListener.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-/**
- * Property change listener gets notified whenever properties are added/deleted/modified.
- */
-public interface PropertyListener {
- /**
- * A new property is being added.
- *
- * @param object The ScriptObject to which property was added.
- * @param prop The new Property added.
- */
- public void propertyAdded(ScriptObject object, Property prop);
-
- /**
- * An existing property is being deleted.
- *
- * @param object The ScriptObject whose property is being deleted.
- * @param prop The property being deleted.
- */
- public void propertyDeleted(ScriptObject object, Property prop);
-
- /**
- * An existing Property is being replaced with a new Property.
- *
- * @param object The ScriptObject whose property is being modified.
- * @param oldProp The old property that is being replaced.
- * @param newProp The new property that replaces the old property.
- *
- */
- public void propertyModified(ScriptObject object, Property oldProp, Property newProp);
-
- /**
- * Given object's __proto__ has changed.
- *
- * @param object object whose __proto__ has changed.
- * @param oldProto old __proto__
- * @param newProto new __proto__
- */
- public void protoChanged(ScriptObject object, ScriptObject oldProto, ScriptObject newProto);
-}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java b/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
deleted file mode 100644
index 27ec2c97..00000000
--- a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * Helper class to manage property listeners and notification.
- */
-public class PropertyListenerManager implements PropertyListener {
- PropertyListenerManager() {}
-
- /** property listeners for this object. */
- private Map<PropertyListener,Boolean> listeners;
-
- // These counters are updated in debug mode
- private static int listenersAdded;
- private static int listenersRemoved;
-
- /**
- * Return aggregate listeners added to all PropertyListenerManagers
- * @return the listenersAdded
- */
- public static int getListenersAdded() {
- return listenersAdded;
- }
-
- /**
- * Return aggregate listeners removed from all PropertyListenerManagers
- * @return the listenersRemoved
- */
- public static int getListenersRemoved() {
- return listenersRemoved;
- }
-
- /**
- * Return listeners added to this PropertyListenerManager.
- * @return the listener count
- */
- public final int getListenerCount() {
- return listeners != null? listeners.size() : 0;
- }
-
- // Property listener management methods
-
- /**
- * Add a property listener to this object.
- *
- * @param listener The property listener that is added.
- */
- public synchronized final void addPropertyListener(final PropertyListener listener) {
- if (listeners == null) {
- listeners = new WeakHashMap<>();
- }
-
- if (Context.DEBUG) {
- listenersAdded++;
- }
- listeners.put(listener, Boolean.TRUE);
- }
-
- /**
- * Remove a property listener from this object.
- *
- * @param listener The property listener that is removed.
- */
- public synchronized final void removePropertyListener(final PropertyListener listener) {
- if (listeners != null) {
- if (Context.DEBUG) {
- listenersRemoved++;
- }
- listeners.remove(listener);
- }
- }
-
- /**
- * This method can be called to notify property addition to this object's listeners.
- *
- * @param object The ScriptObject to which property was added.
- * @param prop The property being added.
- */
- protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyAdded(object, prop);
- }
- }
- }
-
- /**
- * This method can be called to notify property deletion to this object's listeners.
- *
- * @param object The ScriptObject from which property was deleted.
- * @param prop The property being deleted.
- */
- protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyDeleted(object, prop);
- }
- }
- }
-
- /**
- * This method can be called to notify property modification to this object's listeners.
- *
- * @param object The ScriptObject to which property was modified.
- * @param oldProp The old property being replaced.
- * @param newProp The new property that replaces the old property.
- */
- protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.propertyModified(object, oldProp, newProp);
- }
- }
- }
-
- /**
- * This method can be called to notify __proto__ modification to this object's listeners.
- *
- * @param object The ScriptObject whose __proto__ was changed.
- * @param oldProto old __proto__
- * @param newProto new __proto__
- */
- protected synchronized final void notifyProtoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- if (listeners != null) {
- for (PropertyListener listener : listeners.keySet()) {
- listener.protoChanged(object, oldProto, newProto);
- }
- }
- }
-
- // PropertyListener methods
-
- @Override
- public final void propertyAdded(final ScriptObject object, final Property prop) {
- notifyPropertyAdded(object, prop);
- }
-
- @Override
- public final void propertyDeleted(final ScriptObject object, final Property prop) {
- notifyPropertyDeleted(object, prop);
- }
-
- @Override
- public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- notifyPropertyModified(object, oldProp, newProp);
- }
-
- @Override
- public final void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- notifyProtoChanged(object, oldProto, newProto);
- }
-}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
new file mode 100644
index 00000000..532969cc
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Helper class to manage property listeners and notification.
+ */
+public class PropertyListeners {
+
+ private Map<String, WeakPropertyMapSet> listeners;
+
+ // These counters are updated in debug mode
+ private static int listenersAdded;
+ private static int listenersRemoved;
+
+ /**
+ * Copy constructor
+ * @param listener listener to copy
+ */
+ PropertyListeners(final PropertyListeners listener) {
+ if (listener != null && listener.listeners != null) {
+ this.listeners = new WeakHashMap<>(listener.listeners);
+ }
+ }
+
+ /**
+ * Return aggregate listeners added to all PropertyListenerManagers
+ * @return the listenersAdded
+ */
+ public static int getListenersAdded() {
+ return listenersAdded;
+ }
+
+ /**
+ * Return aggregate listeners removed from all PropertyListenerManagers
+ * @return the listenersRemoved
+ */
+ public static int getListenersRemoved() {
+ return listenersRemoved;
+ }
+
+ /**
+ * Return listeners added to this ScriptObject.
+ * @param obj the object
+ * @return the listener count
+ */
+ public static int getListenerCount(final ScriptObject obj) {
+ final PropertyListeners propertyListeners = obj.getMap().getListeners();
+ if (propertyListeners != null) {
+ return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
+ }
+ return 0;
+ }
+
+ // Property listener management methods
+
+ /**
+ * Add {@code propertyMap} as property listener to {@code listeners} using key {@code key} by
+ * creating and returning a new {@code PropertyListeners} instance.
+ *
+ * @param listeners the original property listeners instance, may be null
+ * @param key the property key
+ * @param propertyMap the property map
+ * @return the new property map
+ */
+ public static PropertyListeners addListener(final PropertyListeners listeners, final String key, final PropertyMap propertyMap) {
+ final PropertyListeners newListeners;
+ if (listeners == null || !listeners.containsListener(key, propertyMap)) {
+ newListeners = new PropertyListeners(listeners);
+ newListeners.addListener(key, propertyMap);
+ return newListeners;
+ }
+ return listeners;
+ }
+
+ /**
+ * Checks whether {@code propertyMap} is registered as listener with {@code key}.
+ *
+ * @param key the property key
+ * @param propertyMap the property map
+ * @return true if property map is registered with property key
+ */
+ synchronized boolean containsListener(final String key, final PropertyMap propertyMap) {
+ if (listeners == null) {
+ return false;
+ }
+ WeakPropertyMapSet set = listeners.get(key);
+ return set != null && set.contains(propertyMap);
+ }
+
+ /**
+ * Add a property listener to this object.
+ *
+ * @param propertyMap The property listener that is added.
+ */
+ synchronized final void addListener(final String key, final PropertyMap propertyMap) {
+ if (Context.DEBUG) {
+ listenersAdded++;
+ }
+ if (listeners == null) {
+ listeners = new WeakHashMap<>();
+ }
+
+ WeakPropertyMapSet set = listeners.get(key);
+ if (set == null) {
+ set = new WeakPropertyMapSet();
+ listeners.put(key, set);
+ }
+ if (!set.contains(propertyMap)) {
+ set.add(propertyMap);
+ }
+ }
+
+ /**
+ * A new property is being added.
+ *
+ * @param prop The new Property added.
+ */
+ public synchronized void propertyAdded(final Property prop) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(prop.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyAdded(prop);
+ }
+ listeners.remove(prop.getKey());
+ }
+ }
+ }
+
+ /**
+ * An existing property is being deleted.
+ *
+ * @param prop The property being deleted.
+ */
+ public synchronized void propertyDeleted(final Property prop) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(prop.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyDeleted(prop);
+ }
+ listeners.remove(prop.getKey());
+ }
+ }
+ }
+
+ /**
+ * An existing Property is being replaced with a new Property.
+ *
+ * @param oldProp The old property that is being replaced.
+ * @param newProp The new property that replaces the old property.
+ *
+ */
+ public synchronized void propertyModified(final Property oldProp, final Property newProp) {
+ if (listeners != null) {
+ WeakPropertyMapSet set = listeners.get(oldProp.getKey());
+ if (set != null) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.propertyModified(oldProp, newProp);
+ }
+ listeners.remove(oldProp.getKey());
+ }
+ }
+ }
+
+ public synchronized void protoChanged() {
+ if (listeners != null) {
+ for (WeakPropertyMapSet set : listeners.values()) {
+ for (PropertyMap propertyMap : set.elements()) {
+ propertyMap.protoChanged();
+ }
+ }
+ listeners.clear();
+ }
+ }
+
+ private static class WeakPropertyMapSet {
+
+ private WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
+
+ void add(final PropertyMap propertyMap) {
+ map.put(propertyMap, Boolean.TRUE);
+ }
+
+ boolean contains(final PropertyMap propertyMap) {
+ return map.containsKey(propertyMap);
+ }
+
+ Set<PropertyMap> elements() {
+ return map.keySet();
+ }
+
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/PropertyMap.java b/src/jdk/nashorn/internal/runtime/PropertyMap.java
index 03c4978a..e2e07fdf 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -29,16 +29,19 @@ import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.lang.invoke.SwitchPoint;
-import java.lang.ref.WeakReference;
+import java.lang.ref.SoftReference;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
import java.util.NoSuchElementException;
import java.util.WeakHashMap;
+import jdk.nashorn.internal.scripts.JO;
/**
* Map of object properties. The PropertyMap is the "template" for JavaScript object
@@ -49,23 +52,17 @@ import java.util.WeakHashMap;
* All property maps are immutable. If a property is added, modified or removed, the mutator
* will return a new map.
*/
-public final class PropertyMap implements Iterable<Object>, PropertyListener {
+public final class PropertyMap implements Iterable<Object>, Serializable {
/** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
public static final int NOT_EXTENSIBLE = 0b0000_0001;
/** Does this map contain valid array keys? */
public static final int CONTAINS_ARRAY_KEYS = 0b0000_0010;
- /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */
- private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
- /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
- public static final int IS_LISTENER_ADDED = 0b0001_0000;
- /** Is this process wide "shared" map?. This flag is not copied when cloning a map */
- public static final int IS_SHARED = 0b0010_0000;
/** Map status flags. */
private int flags;
/** Map of properties. */
- private final PropertyHashMap properties;
+ private transient PropertyHashMap properties;
/** Number of fields in use. */
private int fieldCount;
@@ -76,17 +73,22 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
/** Length of spill in use. */
private int spillLength;
+ /** Structure class name */
+ private String className;
+
/** {@link SwitchPoint}s for gets on inherited properties. */
- private Map<String, SwitchPoint> protoGetSwitches;
+ private transient HashMap<String, SwitchPoint> protoGetSwitches;
/** History of maps, used to limit map duplication. */
- private HashMap<Property, PropertyMap> history;
+ private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
/** History of prototypes, used to limit map duplication. */
- private WeakHashMap<ScriptObject, WeakReference<PropertyMap>> protoHistory;
+ private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
+
+ /** property listeners */
+ private transient PropertyListeners listeners;
- /** Cache for hashCode */
- private int hashCode;
+ private static final long serialVersionUID = -7041836752008732533L;
/**
* Constructor.
@@ -97,8 +99,10 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @param spillLength Number of spill slots used.
* @param containsArrayKeys True if properties contain numeric keys
*/
- private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
+ private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
+ final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
this.properties = properties;
+ this.className = className;
this.fieldCount = fieldCount;
this.fieldMaximum = fieldMaximum;
this.spillLength = spillLength;
@@ -119,10 +123,12 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
*/
private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
this.properties = properties;
- this.flags = propertyMap.getClonedFlags();
+ this.flags = propertyMap.flags;
this.spillLength = propertyMap.spillLength;
this.fieldCount = propertyMap.fieldCount;
this.fieldMaximum = propertyMap.fieldMaximum;
+ // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
+ this.listeners = propertyMap.listeners;
if (Context.DEBUG) {
count++;
@@ -151,7 +157,25 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
if (Context.DEBUG) {
duplicatedCount++;
}
- return new PropertyMap(this.properties, 0, 0, 0, containsArrayKeys());
+ return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
+ }
+
+ private void writeObject(final ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeObject(properties.getProperties());
+ }
+
+ private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+
+ final Property[] props = (Property[]) in.readObject();
+ this.properties = EMPTY_HASHMAP.immutableAdd(props);
+
+ assert className != null;
+ final Class<?> structure = Context.forStructureClass(className);
+ for (Property prop : props) {
+ prop.initMethodHandles(structure);
+ }
}
/**
@@ -166,9 +190,9 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @param spillLength Number of used spill slots.
* @return New {@link PropertyMap}.
*/
- public static PropertyMap newMap(final Collection<Property> properties, final int fieldCount, final int fieldMaximum, final int spillLength) {
+ public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum, final int spillLength) {
PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
- return new PropertyMap(newProperties, fieldCount, fieldMaximum, spillLength, false);
+ return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
}
/**
@@ -181,7 +205,7 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New {@link PropertyMap}.
*/
public static PropertyMap newMap(final Collection<Property> properties) {
- return (properties == null || properties.isEmpty())? newMap() : newMap(properties, 0, 0, 0);
+ return (properties == null || properties.isEmpty())? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
}
/**
@@ -190,7 +214,7 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New empty {@link PropertyMap}.
*/
public static PropertyMap newMap() {
- return new PropertyMap(EMPTY_HASHMAP, 0, 0, 0, false);
+ return new PropertyMap(EMPTY_HASHMAP, JO.class.getName(), 0, 0, 0, false);
}
/**
@@ -203,35 +227,92 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * Return a SwitchPoint used to track changes of a property in a prototype.
+ * Get the listeners of this map, or null if none exists
*
- * @param proto Object prototype.
- * @param key {@link Property} key.
+ * @return the listeners
+ */
+ public PropertyListeners getListeners() {
+ return listeners;
+ }
+
+ /**
+ * Add {@code listenerMap} as a listener to this property map for the given {@code key}.
*
- * @return A shared {@link SwitchPoint} for the property.
+ * @param key the property name
+ * @param listenerMap the listener map
+ */
+ public void addListener(final String key, final PropertyMap listenerMap) {
+ if (listenerMap != this) {
+ // We need to clone listener instance when adding a new listener since we share
+ // the listeners instance with our parent maps that don't need to see the new listener.
+ listeners = PropertyListeners.addListener(listeners, key, listenerMap);
+ }
+ }
+
+ /**
+ * A new property is being added.
+ *
+ * @param property The new Property added.
*/
- public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
- assert !isShared() : "proto SwitchPoint from a shared PropertyMap";
+ public void propertyAdded(final Property property) {
+ invalidateProtoGetSwitchPoint(property);
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
+ }
- if (proto == null) {
- return null;
+ /**
+ * An existing property is being deleted.
+ *
+ * @param property The property being deleted.
+ */
+ public void propertyDeleted(final Property property) {
+ invalidateProtoGetSwitchPoint(property);
+ if (listeners != null) {
+ listeners.propertyDeleted(property);
}
+ }
+ /**
+ * An existing property is being redefined.
+ *
+ * @param oldProperty The old property
+ * @param newProperty The new property
+ */
+ public void propertyModified(final Property oldProperty, final Property newProperty) {
+ invalidateProtoGetSwitchPoint(oldProperty);
+ if (listeners != null) {
+ listeners.propertyModified(oldProperty, newProperty);
+ }
+ }
+
+ /**
+ * The prototype of an object associated with this {@link PropertyMap} is changed.
+ */
+ public void protoChanged() {
+ invalidateAllProtoGetSwitchPoints();
+ if (listeners != null) {
+ listeners.protoChanged();
+ }
+ }
+
+ /**
+ * Return a SwitchPoint used to track changes of a property in a prototype.
+ *
+ * @param key Property key.
+ * @return A shared {@link SwitchPoint} for the property.
+ */
+ public synchronized SwitchPoint getSwitchPoint(final String key) {
if (protoGetSwitches == null) {
protoGetSwitches = new HashMap<>();
- if (! isListenerAdded()) {
- proto.addPropertyListener(this);
- setIsListenerAdded();
- }
}
- if (protoGetSwitches.containsKey(key)) {
- return protoGetSwitches.get(key);
+ SwitchPoint switchPoint = protoGetSwitches.get(key);
+ if (switchPoint == null) {
+ switchPoint = new SwitchPoint();
+ protoGetSwitches.put(key, switchPoint);
}
- final SwitchPoint switchPoint = new SwitchPoint();
- protoGetSwitches.put(key, switchPoint);
-
return switchPoint;
}
@@ -240,14 +321,13 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
*
* @param property {@link Property} to invalidate.
*/
- private void invalidateProtoGetSwitchPoint(final Property property) {
- assert !isShared() : "proto invalidation on a shared PropertyMap";
-
+ synchronized void invalidateProtoGetSwitchPoint(final Property property) {
if (protoGetSwitches != null) {
+
final String key = property.getKey();
final SwitchPoint sp = protoGetSwitches.get(key);
if (sp != null) {
- protoGetSwitches.put(key, new SwitchPoint());
+ protoGetSwitches.remove(key);
if (Context.DEBUG) {
protoInvalidations++;
}
@@ -257,14 +337,15 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * Indicate that proto itself has changed in hierachy somewhere.
+ * Indicate that proto itself has changed in hierarchy somewhere.
*/
- private void invalidateAllProtoGetSwitchPoints() {
- assert !isShared() : "proto invalidation on a shared PropertyMap";
-
- if (protoGetSwitches != null) {
- final Collection<SwitchPoint> sws = protoGetSwitches.values();
- SwitchPoint.invalidateAll(sws.toArray(new SwitchPoint[sws.size()]));
+ synchronized void invalidateAllProtoGetSwitchPoints() {
+ if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
+ if (Context.DEBUG) {
+ protoInvalidations += protoGetSwitches.size();
+ }
+ SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
+ protoGetSwitches.clear();
}
}
@@ -279,7 +360,33 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New {@link PropertyMap} with {@link Property} added.
*/
PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
- return addProperty(new AccessorProperty(property, bindTo));
+ // No need to store bound property in the history as bound properties can't be reused.
+ return addPropertyNoHistory(new AccessorProperty(property, bindTo));
+ }
+
+ /**
+ * Add a property to the map without adding it to the history. This should be used for properties that
+ * can't be shared such as bound properties, or properties that are expected to be added only once.
+ *
+ * @param property {@link Property} being added.
+ * @return New {@link PropertyMap} with {@link Property} added.
+ */
+ public PropertyMap addPropertyNoHistory(final Property property) {
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
+ final PropertyHashMap newProperties = properties.immutableAdd(property);
+ final PropertyMap newMap = new PropertyMap(this, newProperties);
+
+ if(!property.isSpill()) {
+ newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
+ }
+ if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
+ newMap.setContainsArrayKeys();
+ }
+
+ newMap.spillLength += property.getSpillCount();
+ return newMap;
}
/**
@@ -290,6 +397,9 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New {@link PropertyMap} with {@link Property} added.
*/
public PropertyMap addProperty(final Property property) {
+ if (listeners != null) {
+ listeners.propertyAdded(property);
+ }
PropertyMap newMap = checkHistory(property);
if (newMap == null) {
@@ -318,6 +428,9 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
*/
public PropertyMap deleteProperty(final Property property) {
+ if (listeners != null) {
+ listeners.propertyDeleted(property);
+ }
PropertyMap newMap = checkHistory(property);
final String key = property.getKey();
@@ -339,6 +452,9 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return New {@link PropertyMap} with {@link Property} replaced.
*/
PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
+ if (listeners != null) {
+ listeners.propertyModified(oldProperty, newProperty);
+ }
// Add replaces existing property.
final PropertyHashMap newProperties = properties.immutableAdd(newProperty);
final PropertyMap newMap = new PropertyMap(this, newProperties);
@@ -363,7 +479,7 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
(oldProperty instanceof AccessorProperty &&
newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
- newMap.flags = getClonedFlags();
+ newMap.flags = flags;
/*
* spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
@@ -491,28 +607,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * Make this property map 'shared' one. Shared property map instances are
- * process wide singleton objects. A shaped map should never be added as a listener
- * to a proto object. Nor it should have history or proto history. A shared map
- * is just a template that is meant to be duplicated before use. All nasgen initialized
- * property maps are shared.
- *
- * @return this map after making it as shared
- */
- public PropertyMap setIsShared() {
- assert !isListenerAdded() : "making PropertyMap shared after listener added";
- assert protoHistory == null : "making PropertyMap shared after associating a proto with it";
- if (Context.DEBUG) {
- sharedCount++;
- }
-
- flags |= IS_SHARED;
- // clear any history on this PropertyMap, won't be used.
- history = null;
- return this;
- }
-
- /**
* Check for any configurable properties.
*
* @return {@code true} if any configurable.
@@ -551,14 +645,14 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
/**
* Check prototype history for an existing property map with specified prototype.
*
- * @param newProto New prototype object.
+ * @param parentMap New prototype object.
*
* @return Existing {@link PropertyMap} or {@code null} if not found.
*/
- private PropertyMap checkProtoHistory(final ScriptObject newProto) {
+ private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
final PropertyMap cachedMap;
if (protoHistory != null) {
- final WeakReference<PropertyMap> weakMap = protoHistory.get(newProto);
+ final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
cachedMap = (weakMap != null ? weakMap.get() : null);
} else {
cachedMap = null;
@@ -574,17 +668,15 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
/**
* Add a map to the prototype history.
*
- * @param newProto Prototype to add (key.)
+ * @param parentMap Prototype to add (key.)
* @param newMap {@link PropertyMap} associated with prototype.
*/
- private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
- assert !isShared() : "proto history modified on a shared PropertyMap";
-
+ private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
if (protoHistory == null) {
protoHistory = new WeakHashMap<>();
}
- protoHistory.put(newProto, new WeakReference<>(newMap));
+ protoHistory.put(parentMap, new SoftReference<>(newMap));
}
/**
@@ -594,14 +686,12 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @param newMap Modified {@link PropertyMap}.
*/
private void addToHistory(final Property property, final PropertyMap newMap) {
- assert !isShared() : "history modified on a shared PropertyMap";
-
if (!properties.isEmpty()) {
if (history == null) {
- history = new LinkedHashMap<>();
+ history = new WeakHashMap<>();
}
- history.put(property, newMap);
+ history.put(property, new SoftReference<>(newMap));
}
}
@@ -613,8 +703,10 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
* @return Existing map or {@code null} if not found.
*/
private PropertyMap checkHistory(final Property property) {
+
if (history != null) {
- PropertyMap historicMap = history.get(property);
+ SoftReference<PropertyMap> ref = history.get(property);
+ final PropertyMap historicMap = ref == null ? null : ref.get();
if (historicMap != null) {
if (Context.DEBUG) {
@@ -628,54 +720,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
return null;
}
- /**
- * Calculate the hash code for the map.
- *
- * @return Computed hash code.
- */
- private int computeHashCode() {
- int hash = 0;
-
- for (final Property property : getProperties()) {
- hash = hash << 7 ^ hash >> 7;
- hash ^= property.hashCode();
- }
-
- return hash;
- }
-
- @Override
- public int hashCode() {
- if (hashCode == 0 && !properties.isEmpty()) {
- hashCode = computeHashCode();
- }
- return hashCode;
- }
-
- @Override
- public boolean equals(final Object other) {
- if (!(other instanceof PropertyMap)) {
- return false;
- }
-
- final PropertyMap otherMap = (PropertyMap)other;
-
- if (properties.size() != otherMap.properties.size()) {
- return false;
- }
-
- final Iterator<Property> iter = properties.values().iterator();
- final Iterator<Property> otherIter = otherMap.properties.values().iterator();
-
- while (iter.hasNext() && otherIter.hasNext()) {
- if (!iter.next().equals(otherIter.next())) {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
@@ -728,24 +772,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * Check whether a {@link PropertyListener} has been added to this map.
- *
- * @return {@code true} if {@link PropertyListener} exists
- */
- public boolean isListenerAdded() {
- return (flags & IS_LISTENER_ADDED) != 0;
- }
-
- /**
- * Check if this map shared or not.
- *
- * @return true if this map is shared.
- */
- public boolean isShared() {
- return (flags & IS_SHARED) != 0;
- }
-
- /**
* Test to see if {@link PropertyMap} is extensible.
*
* @return {@code true} if {@link PropertyMap} can be added to.
@@ -800,50 +826,29 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * Change the prototype of objects associated with this {@link PropertyMap}.
+ * Return a property map with the same layout that is associated with the new prototype object.
*
- * @param oldProto Current prototype object.
* @param newProto New prototype object to replace oldProto.
- *
* @return New {@link PropertyMap} with prototype changed.
*/
- PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
- assert !isShared() : "proto associated with a shared PropertyMap";
-
- if (oldProto == newProto) {
- return this;
- }
+ public PropertyMap changeProto(final ScriptObject newProto) {
- final PropertyMap nextMap = checkProtoHistory(newProto);
+ final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
+ final PropertyMap nextMap = checkProtoHistory(parentMap);
if (nextMap != null) {
return nextMap;
}
if (Context.DEBUG) {
- incrementSetProtoNewMapCount();
+ setProtoNewMapCount++;
}
final PropertyMap newMap = new PropertyMap(this);
- addToProtoHistory(newProto, newMap);
+ addToProtoHistory(parentMap, newMap);
return newMap;
}
- /**
- * Indicate that the map has listeners.
- */
- private void setIsListenerAdded() {
- flags |= IS_LISTENER_ADDED;
- }
-
- /**
- * Return only the flags that should be copied during cloning.
- *
- * @return Subset of flags that should be copied.
- */
- private int getClonedFlags() {
- return flags & CLONEABLE_FLAGS_MASK;
- }
/**
* {@link PropertyMap} iterator.
@@ -900,41 +905,12 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/*
- * PropertyListener implementation.
- */
-
- @Override
- public void propertyAdded(final ScriptObject object, final Property prop) {
- invalidateProtoGetSwitchPoint(prop);
- }
-
- @Override
- public void propertyDeleted(final ScriptObject object, final Property prop) {
- invalidateProtoGetSwitchPoint(prop);
- }
-
- @Override
- public void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
- invalidateProtoGetSwitchPoint(oldProp);
- }
-
- @Override
- public void protoChanged(final ScriptObject object, final ScriptObject oldProto, final ScriptObject newProto) {
- // We may walk and invalidate SwitchPoints for properties inherited
- // from 'object' or it's old proto chain. But, it may not be worth it.
- // For example, a new proto may have a user defined getter/setter for
- // a data property down the chain. So, invalidating all is better.
- invalidateAllProtoGetSwitchPoints();
- }
-
- /*
* Debugging and statistics.
*/
// counters updated only in debug mode
private static int count;
private static int clonedCount;
- private static int sharedCount;
private static int duplicatedCount;
private static int historyHit;
private static int protoInvalidations;
@@ -956,13 +932,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
}
/**
- * @return The number of maps that are shared.
- */
- public static int getSharedCount() {
- return sharedCount;
- }
-
- /**
* @return The number of maps that are duplicated.
*/
public static int getDuplicatedCount() {
@@ -997,10 +966,4 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
return setProtoNewMapCount;
}
- /**
- * Increment the prototype set count.
- */
- private static void incrementSetProtoNewMapCount() {
- setProtoNewMapCount++;
- }
}
diff --git a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index e5ca3c9a..90885444 100644
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -27,14 +27,15 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
+import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
+import java.util.Map;
import jdk.internal.dynalink.support.NameCodec;
-
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.FunctionSignature;
@@ -43,6 +44,7 @@ import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.parser.Token;
import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.scripts.JS;
/**
* This is a subclass that represents a script function that may be regenerated,
@@ -50,13 +52,19 @@ import jdk.nashorn.internal.parser.TokenType;
* The common denominator is that it can get new invokers during its lifespan,
* unlike {@code FinalScriptFunctionData}
*/
-public final class RecompilableScriptFunctionData extends ScriptFunctionData {
+public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Serializable {
/** FunctionNode with the code for this ScriptFunction */
- private FunctionNode functionNode;
+ private transient FunctionNode functionNode;
/** Source from which FunctionNode was parsed. */
- private final Source source;
+ private transient Source source;
+
+ /** The line number where this function begins. */
+ private final int lineNumber;
+
+ /** Allows us to retrieve the method handle for this function once the code is compiled */
+ private MethodLocator methodLocator;
/** Token of this function within the source. */
private final long token;
@@ -65,13 +73,13 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
private final PropertyMap allocatorMap;
/** Code installer used for all further recompilation/specialization of this ScriptFunction */
- private CodeInstaller<ScriptEnvironment> installer;
+ private transient CodeInstaller<ScriptEnvironment> installer;
/** Name of class where allocator function resides */
private final String allocatorClassName;
/** lazily generated allocator */
- private MethodHandle allocator;
+ private transient MethodHandle allocator;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
@@ -79,7 +87,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
* Used for specialization based on runtime arguments. Whenever we specialize on
* callsite parameter types at runtime, we need to use a parameter type guard to
* ensure that the specialized version of the script function continues to be
- * applicable for a particular callsite *
+ * applicable for a particular callsite.
*/
private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class, Object[].class);
@@ -88,10 +96,12 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
* (or java.lang.Number instance) to specialize the parameter to an integer, if the
* parameter in question can be represented as one. The double typically only exists
* because the compiler doesn't know any better than "a number type" and conservatively
- * picks doubles when it can't prove that an integer addition wouldn't overflow
+ * picks doubles when it can't prove that an integer addition wouldn't overflow.
*/
private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
+ private static final long serialVersionUID = 4914839316174633726L;
+
/**
* Constructor - public as scripts use it
*
@@ -103,16 +113,17 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
super(functionName(functionNode),
functionNode.getParameters().size(),
- functionNode.isStrict(),
- false,
- true);
-
+ getFlags(functionNode));
this.functionNode = functionNode;
this.source = functionNode.getSource();
+ this.lineNumber = functionNode.getLineNumber();
this.token = tokenFor(functionNode);
this.installer = installer;
this.allocatorClassName = allocatorClassName;
this.allocatorMap = allocatorMap;
+ if (!functionNode.isLazy()) {
+ methodLocator = new MethodLocator(functionNode);
+ }
}
@Override
@@ -124,15 +135,19 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
return "function " + (name == null ? "" : name) + "() { [native code] }";
}
+ public void setCodeAndSource(final Map<String, Class<?>> code, final Source source) {
+ this.source = source;
+ if (methodLocator != null) {
+ methodLocator.setClass(code.get(methodLocator.getClassName()));
+ }
+ }
+
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
if (source != null) {
- sb.append(source.getName())
- .append(':')
- .append(functionNode.getLineNumber())
- .append(' ');
+ sb.append(source.getName()).append(':').append(lineNumber).append(' ');
}
return sb.toString() + super.toString();
@@ -159,11 +174,25 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
return Token.toDesc(TokenType.FUNCTION, position, length);
}
+ private static int getFlags(final FunctionNode functionNode) {
+ int flags = IS_CONSTRUCTOR;
+ if (functionNode.isStrict()) {
+ flags |= IS_STRICT;
+ }
+ if (functionNode.needsCallee()) {
+ flags |= NEEDS_CALLEE;
+ }
+ if (functionNode.usesThis() || functionNode.hasEval()) {
+ flags |= USES_THIS;
+ }
+ return flags;
+ }
+
@Override
- ScriptObject allocate() {
+ ScriptObject allocate(final PropertyMap map) {
try {
ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
- return allocator == null ? null : (ScriptObject)allocator.invokeExact(allocatorMap);
+ return allocator == null ? null : (ScriptObject)allocator.invokeExact(map);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
@@ -178,40 +207,52 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
}
@Override
+ PropertyMap getAllocatorMap() {
+ return allocatorMap;
+ }
+
+
+ @Override
+ protected void ensureCompiled() {
+ if (functionNode != null && functionNode.isLazy()) {
+ Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
+ final Compiler compiler = new Compiler(installer);
+ functionNode = compiler.compile(functionNode);
+ assert !functionNode.isLazy();
+ compiler.install(functionNode);
+ methodLocator = new MethodLocator(functionNode);
+ flags = getFlags(functionNode);
+ }
+
+ if (functionNode != null) {
+ methodLocator.setClass(functionNode.getCompileUnit().getCode());
+ }
+ }
+
+ @Override
protected synchronized void ensureCodeGenerated() {
- if (!code.isEmpty()) {
- return; // nothing to do, we have code, at least some.
- }
-
- if (functionNode.isLazy()) {
- Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
- final Compiler compiler = new Compiler(installer);
- functionNode = compiler.compile(functionNode);
- assert !functionNode.isLazy();
- compiler.install(functionNode);
-
- /*
- * We don't need to update any flags - varArgs and needsCallee are instrincic
- * in the function world we need to get a destination node from the compile instead
- * and replace it with our function node. TODO
- */
- }
-
- /*
- * We can't get to this program point unless we have bytecode, either from
- * eager compilation or from running a lazy compile on the lines above
- */
-
- assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
-
- // code exists - look it up and add it into the automatically sorted invoker list
- addCode(functionNode);
-
- if (! functionNode.canSpecialize()) {
- // allow GC to claim IR stuff that is not needed anymore
- functionNode = null;
- installer = null;
- }
+ if (!code.isEmpty()) {
+ return; // nothing to do, we have code, at least some.
+ }
+
+ ensureCompiled();
+
+ /*
+ * We can't get to this program point unless we have bytecode, either from
+ * eager compilation or from running a lazy compile on the lines above
+ */
+
+ assert functionNode == null || functionNode.hasState(CompilationState.EMITTED) :
+ functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
+
+ // code exists - look it up and add it into the automatically sorted invoker list
+ addCode(functionNode);
+
+ if (functionNode != null && !functionNode.canSpecialize()) {
+ // allow GC to claim IR stuff that is not needed anymore
+ functionNode = null;
+ installer = null;
+ }
}
private MethodHandle addCode(final FunctionNode fn) {
@@ -219,13 +260,9 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
}
private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
- final MethodType targetType = new FunctionSignature(fn).getMethodType();
- MethodHandle target =
- MH.findStatic(
- LOOKUP,
- fn.getCompileUnit().getCode(),
- fn.getName(),
- targetType);
+ assert methodLocator != null;
+ MethodHandle target = methodLocator.getMethodHandle();
+ final MethodType targetType = methodLocator.getMethodType();
/*
* For any integer argument. a double that is representable as an integer is OK.
@@ -405,7 +442,6 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
- assert snapshot != null;
assert snapshot != functionNode;
final Compiler compiler = new Compiler(installer);
@@ -431,5 +467,45 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData {
return MH.findStatic(MethodHandles.lookup(), RecompilableScriptFunctionData.class, name, MH.type(rtype, types));
}
+ /**
+ * Helper class that allows us to retrieve the method handle for this function once it has been generated.
+ */
+ private static class MethodLocator implements Serializable {
+ private transient Class<?> clazz;
+ private final String className;
+ private final String methodName;
+ private final MethodType methodType;
+
+ private static final long serialVersionUID = -5420835725902966692L;
+
+ MethodLocator(final FunctionNode functionNode) {
+ this.className = functionNode.getCompileUnit().getUnitClassName();
+ this.methodName = functionNode.getName();
+ this.methodType = new FunctionSignature(functionNode).getMethodType();
+
+ assert className != null;
+ assert methodName != null;
+ }
+
+ void setClass(final Class<?> clazz) {
+ if (!JS.class.isAssignableFrom(clazz)) {
+ throw new IllegalArgumentException();
+ }
+ this.clazz = clazz;
+ }
+
+ String getClassName() {
+ return className;
+ }
+
+ MethodType getMethodType() {
+ return methodType;
+ }
+
+ MethodHandle getMethodHandle() {
+ return MH.findStatic(LOOKUP, clazz, methodName, methodType);
+ }
+ }
+
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 53274710..445106d7 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -62,6 +62,9 @@ public final class ScriptEnvironment {
/** Only compile script, do not run it or generate other ScriptObjects */
public final boolean _compile_only;
+ /** Accept "const" keyword and treat it as variable. Interim feature */
+ public final boolean _const_as_var;
+
/** Accumulated callsite flags that will be used when bootstrapping script callsites */
public final int _callsite_flags;
@@ -134,6 +137,9 @@ public final class ScriptEnvironment {
/** Only parse the source code, do not compile */
public final boolean _parse_only;
+ /** Enable disk cache for compiled scripts */
+ public final boolean _persistent_cache;
+
/** Print the AST before lowering */
public final boolean _print_ast;
@@ -197,6 +203,7 @@ public final class ScriptEnvironment {
_class_cache_size = options.getInteger("class.cache.size");
_compile_only = options.getBoolean("compile.only");
+ _const_as_var = options.getBoolean("const.as.var");
_debug_lines = options.getBoolean("debug.lines");
_dest_dir = options.getString("d");
_dump_on_error = options.getBoolean("doe");
@@ -218,6 +225,7 @@ public final class ScriptEnvironment {
_no_syntax_extensions = options.getBoolean("no.syntax.extensions");
_no_typed_arrays = options.getBoolean("no.typed.arrays");
_parse_only = options.getBoolean("parse.only");
+ _persistent_cache = options.getBoolean("persistent.code.cache");
_print_ast = options.getBoolean("print.ast");
_print_lower_ast = options.getBoolean("print.lower.ast");
_print_code = options.getBoolean("print.code");
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
index d0669d70..3d8b4ff2 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -38,6 +38,7 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -66,6 +67,8 @@ public abstract class ScriptFunction extends ScriptObject {
private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+ private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+
/** method handle to scope getter for this ScriptFunction */
public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
@@ -80,6 +83,9 @@ public abstract class ScriptFunction extends ScriptObject {
private final ScriptFunctionData data;
+ /** The property map used for newly allocated object when function is used as constructor. */
+ protected PropertyMap allocatorMap;
+
/**
* Constructor
*
@@ -88,9 +94,7 @@ public abstract class ScriptFunction extends ScriptObject {
* @param map property map
* @param scope scope
* @param specs specialized version of this function - other method handles
- * @param strict is this a strict mode function?
- * @param builtin is this a built in function?
- * @param isConstructor is this a constructor?
+ * @param flags {@link ScriptFunctionData} flags
*/
protected ScriptFunction(
final String name,
@@ -98,11 +102,9 @@ public abstract class ScriptFunction extends ScriptObject {
final PropertyMap map,
final ScriptObject scope,
final MethodHandle[] specs,
- final boolean strict,
- final boolean builtin,
- final boolean isConstructor) {
+ final int flags) {
- this(new FinalScriptFunctionData(name, methodHandle, specs, strict, builtin, isConstructor), map, scope);
+ this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
}
/**
@@ -125,6 +127,7 @@ public abstract class ScriptFunction extends ScriptObject {
this.data = data;
this.scope = scope;
+ this.allocatorMap = data.getAllocatorMap();
}
@Override
@@ -229,16 +232,16 @@ public abstract class ScriptFunction extends ScriptObject {
}
assert !isBoundFunction(); // allocate never invoked on bound functions
- final ScriptObject object = data.allocate();
+ final ScriptObject object = data.allocate(allocatorMap);
if (object != null) {
Object prototype = getPrototype();
if (prototype instanceof ScriptObject) {
- object.setProto((ScriptObject)prototype);
+ object.setInitialProto((ScriptObject)prototype);
}
if (object.getProto() == null) {
- object.setProto(getObjectPrototype());
+ object.setInitialProto(getObjectPrototype());
}
}
@@ -473,7 +476,14 @@ public abstract class ScriptFunction extends ScriptObject {
if (obj instanceof ScriptObject || !ScriptFunctionData.isPrimitiveThis(obj)) {
return obj;
}
- return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(obj);
+ return Context.getGlobal().wrapAsObject(obj);
+ }
+
+
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ // replace whatever we get with the current global object
+ return Context.getGlobal();
}
/**
@@ -491,11 +501,11 @@ public abstract class ScriptFunction extends ScriptObject {
@Override
protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType type = desc.getMethodType();
+ final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
if (request.isCallSiteUnstable()) {
- // (this, callee, args...) => (this, callee, args[])
- final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class,
- type.parameterCount() - 2);
+ // (callee, this, args...) => (callee, this, args[])
+ final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
// If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
// generic "is this a ScriptFunction?" guard.
@@ -506,17 +516,12 @@ public abstract class ScriptFunction extends ScriptObject {
MethodHandle boundHandle;
MethodHandle guard = null;
- final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
-
if (data.needsCallee()) {
final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
- if (scopeCall) {
+ if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (callee, this, args...) => (callee, args...)
- boundHandle = MH.insertArguments(callHandle, 1, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (callee, args...) => (callee, [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 1, Object.class);
-
+ // (callee, this, args...) => (callee, [this], args...)
+ boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);
} else {
// It's already (callee, this, args...), just what we need
boundHandle = callHandle;
@@ -527,12 +532,12 @@ public abstract class ScriptFunction extends ScriptObject {
// NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
// current lookup as its "this" so it can do security-sensitive creation of adapter classes.
boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
- } else if (scopeCall) {
+ } else if (scopeCall && needsWrappedThis()) {
// Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
- // (this, args...) => (args...)
- boundHandle = MH.bindTo(callHandle, needsWrappedThis() ? Context.getGlobalTrusted() : ScriptRuntime.UNDEFINED);
- // (args...) => ([callee], [this], args...)
- boundHandle = MH.dropArguments(boundHandle, 0, Object.class, Object.class);
+ // (this, args...) => ([this], args...)
+ boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
+ // ([this], args...) => ([callee], [this], args...)
+ boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
} else {
// (this, args...) => ([callee], this, args...)
boundHandle = MH.dropArguments(callHandle, 0, Object.class);
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 4dbbfba9..ad40d622 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -29,6 +29,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import java.io.Serializable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@@ -39,7 +40,7 @@ import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
* Instances of this class are created during codegen and stored in script classes'
* constants array to reduce function instantiation overhead during runtime.
*/
-public abstract class ScriptFunctionData {
+public abstract class ScriptFunctionData implements Serializable {
/** Name of the function or "" for anonynous functions */
protected final String name;
@@ -47,33 +48,46 @@ public abstract class ScriptFunctionData {
/** All versions of this function that have been generated to code */
protected final CompiledFunctions code;
- private int arity;
-
- private final boolean isStrict;
-
- private final boolean isBuiltin;
+ /** Function flags */
+ protected int flags;
- private final boolean isConstructor;
+ private int arity;
private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
+ /** Is this a strict mode function? */
+ public static final int IS_STRICT = 1 << 0;
+ /** Is this a built-in function? */
+ public static final int IS_BUILTIN = 1 << 1;
+ /** Is this a constructor function? */
+ public static final int IS_CONSTRUCTOR = 1 << 2;
+ /** Does this function expect a callee argument? */
+ public static final int NEEDS_CALLEE = 1 << 3;
+ /** Does this function make use of the this-object argument? */
+ public static final int USES_THIS = 1 << 4;
+
+ /** Flag for strict or built-in functions */
+ public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
+ /** Flag for built-in constructors */
+ public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR;
+ /** Flag for strict constructors */
+ public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR;
+
+ private static final long serialVersionUID = 4252901245508769114L;
+
/**
* Constructor
*
* @param name script function name
* @param arity arity
- * @param isStrict is the function strict
- * @param isBuiltin is the function built in
- * @param isConstructor is the function a constructor
+ * @param flags the function flags
*/
- ScriptFunctionData(final String name, final int arity, final boolean isStrict, final boolean isBuiltin, final boolean isConstructor) {
- this.name = name;
- this.arity = arity;
- this.code = new CompiledFunctions();
- this.isStrict = isStrict;
- this.isBuiltin = isBuiltin;
- this.isConstructor = isConstructor;
+ ScriptFunctionData(final String name, final int arity, final int flags) {
+ this.name = name;
+ this.arity = arity;
+ this.code = new CompiledFunctions();
+ this.flags = flags;
}
final int getArity() {
@@ -105,21 +119,21 @@ public abstract class ScriptFunctionData {
* @return true if strict, false otherwise
*/
public boolean isStrict() {
- return isStrict;
+ return (flags & IS_STRICT) != 0;
}
boolean isBuiltin() {
- return isBuiltin;
+ return (flags & IS_BUILTIN) != 0;
}
boolean isConstructor() {
- return isConstructor;
+ return (flags & IS_CONSTRUCTOR) != 0;
}
boolean needsCallee() {
- // we don't know if we need a callee or not unless we are generated
- ensureCodeGenerated();
- return code.needsCallee();
+ // we don't know if we need a callee or not unless code has been compiled
+ ensureCompiled();
+ return (flags & NEEDS_CALLEE) != 0;
}
/**
@@ -128,7 +142,7 @@ public abstract class ScriptFunctionData {
* @return true if this argument must be an object
*/
boolean needsWrappedThis() {
- return !isStrict && !isBuiltin;
+ return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
}
String toSource() {
@@ -202,6 +216,15 @@ public abstract class ScriptFunctionData {
}
/**
+ * If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
+ * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance;
+ * use {@link #ensureCodeGenerated()} to install the actual method handles.
+ */
+ protected void ensureCompiled() {
+ //empty
+ }
+
+ /**
* Return a generic Object/Object invoker for this method. It will ensure code
* is generated, get the most generic of all versions of this function and adapt it
* to Objects.
@@ -229,9 +252,20 @@ public abstract class ScriptFunctionData {
/**
* Allocates an object using this function's allocator.
+ *
+ * @param map the property map for the allocated object.
* @return the object allocated using this function's allocator, or null if the function doesn't have an allocator.
*/
- ScriptObject allocate() {
+ ScriptObject allocate(final PropertyMap map) {
+ return null;
+ }
+
+ /**
+ * Get the property map to use for objects allocated by this function.
+ *
+ * @return the property map for allocated objects.
+ */
+ PropertyMap getAllocatorMap() {
return null;
}
@@ -248,6 +282,8 @@ public abstract class ScriptFunctionData {
final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
final int length = args == null ? 0 : args.length;
+ // Clear the callee and this flags
+ final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
CompiledFunctions boundList = new CompiledFunctions();
if (code.size() == 1) {
@@ -262,8 +298,7 @@ public abstract class ScriptFunctionData {
boundList.add(bind(inv, fn, self, allArgs));
}
- ScriptFunctionData boundData = new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, isStrict(), isBuiltin(), isConstructor());
- return boundData;
+ return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags);
}
/**
@@ -340,11 +375,11 @@ public abstract class ScriptFunctionData {
private Object convertThisObject(final Object thiz) {
if (!(thiz instanceof ScriptObject) && needsWrappedThis()) {
if (JSType.nullOrUndefined(thiz)) {
- return Context.getGlobalTrusted();
+ return Context.getGlobal();
}
if (isPrimitiveThis(thiz)) {
- return ((GlobalObject)Context.getGlobalTrusted()).wrapAsObject(thiz);
+ return Context.getGlobal().wrapAsObject(thiz);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
index 78185b1c..52c98d40 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -70,9 +70,8 @@ final class ScriptLoader extends NashornLoader {
* @return Installed class.
*/
synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) {
- if (cs == null) {
- return defineClass(name, data, 0, data.length, new ProtectionDomain(null, getPermissions(null)));
- }
+ // null check
+ cs.getClass();
return defineClass(name, data, 0, data.length, cs);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java
index 02160d69..d4556d89 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -43,6 +43,7 @@ import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,6 +66,7 @@ import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -88,8 +90,8 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards;
* </ul>
*/
-public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess {
- /** __proto__ special property name */
+public abstract class ScriptObject implements PropertyAccess {
+ /** __proto__ special property name inside object literals. ES6 draft. */
public static final String PROTO_PROPERTY_NAME = "__proto__";
/** Search fall back routine name for "no such method" */
@@ -107,9 +109,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/** Per ScriptObject flag - is this an arguments object? */
public static final int IS_ARGUMENTS = 0b0000_0100;
- /** Is this a prototype PropertyMap? */
- public static final int IS_PROTOTYPE = 0b0000_1000;
-
/** Is length property not-writable? */
public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
@@ -131,9 +130,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/** Indexed array data. */
private ArrayData arrayData;
- static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
- static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
- static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
+ /** Method handle to retrive prototype of this object */
+ public static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
+ /** Method handle to set prototype of this object */
+ public static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
+ static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
+ static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
@@ -143,6 +145,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
+ private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
+
/** Method handle for getting a function argument at a given index. Used from MapCreator */
public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
@@ -153,7 +157,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
/** Method handle for setting the proto of a ScriptObject */
- public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class);
+ public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
/** Method handle for setting the proto of a ScriptObject after checking argument */
public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
@@ -199,10 +203,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
this.arrayData = ArrayData.EMPTY_ARRAY;
this.setMap(map == null ? PropertyMap.newMap() : map);
this.proto = proto;
-
- if (proto != null) {
- proto.setIsPrototype();
- }
}
/**
@@ -229,8 +229,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final Property oldProp = newMap.findProperty(key);
if (oldProp == null) {
if (property instanceof UserAccessorProperty) {
+ // Note: we copy accessor functions to this object which is semantically different from binding.
final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
- newMap = newMap.addProperty(prop);
+ newMap = newMap.addPropertyNoHistory(prop);
} else {
newMap = newMap.addPropertyBind((AccessorProperty)property, source);
}
@@ -326,18 +327,18 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return property descriptor
*/
public final PropertyDescriptor toPropertyDescriptor() {
- final GlobalObject global = (GlobalObject) Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor desc;
if (isDataDescriptor()) {
if (has(SET) || has(GET)) {
- throw typeError((ScriptObject)global, "inconsistent.property.descriptor");
+ throw typeError(global, "inconsistent.property.descriptor");
}
desc = global.newDataDescriptor(UNDEFINED, false, false, false);
} else if (isAccessorDescriptor()) {
if (has(VALUE) || has(WRITABLE)) {
- throw typeError((ScriptObject)global, "inconsistent.property.descriptor");
+ throw typeError(global, "inconsistent.property.descriptor");
}
desc = global.newAccessorDescriptor(UNDEFINED, UNDEFINED, false, false);
@@ -356,7 +357,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*
* @return property descriptor
*/
- public static PropertyDescriptor toPropertyDescriptor(final ScriptObject global, final Object obj) {
+ public static PropertyDescriptor toPropertyDescriptor(final Global global, final Object obj) {
if (obj instanceof ScriptObject) {
return ((ScriptObject)obj).toPropertyDescriptor();
}
@@ -375,7 +376,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
public Object getOwnPropertyDescriptor(final String key) {
final Property property = getMap().findProperty(key);
- final GlobalObject global = (GlobalObject)Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
if (property != null) {
final ScriptFunction get = property.getGetterFunction(this);
@@ -440,7 +441,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return true if property was successfully defined
*/
public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor desc = toPropertyDescriptor(global, propertyDesc);
final Object current = getOwnPropertyDescriptor(key);
final String name = JSType.toString(key);
@@ -467,7 +468,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return true;
}
- if (currentDesc.equals(newDesc)) {
+ if (newDesc.hasAndEquals(currentDesc)) {
// every descriptor field of the new is same as the current
return true;
}
@@ -594,23 +595,16 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
- * Spec. mentions use of [[DefineOwnProperty]] for indexed properties in
- * certain places (eg. Array.prototype.map, filter). We can not use ScriptObject.set
- * method in such cases. This is because set method uses inherited setters (if any)
- * from any object in proto chain such as Array.prototype, Object.prototype.
- * This method directly sets a particular element value in the current object.
+ * Almost like defineOwnProperty(int,Object) for arrays this one does
+ * not add 'gap' elements (like the array one does).
*
* @param index key for property
* @param value value to define
*/
- public final void defineOwnProperty(final int index, final Object value) {
+ public void defineOwnProperty(final int index, final Object value) {
assert isValidArrayIndex(index) : "invalid array index";
final long longIndex = ArrayIndex.toLongIndex(index);
- if (longIndex >= getArray().length()) {
- // make array big enough to hold..
- setArray(getArray().ensure(longIndex));
- }
- setArray(getArray().set(index, value, false));
+ setValueAtArrayIndex(longIndex, index, value, false);
}
private void checkIntegerKey(final String key) {
@@ -638,7 +632,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final int propFlags = Property.toFlags(pdesc);
if (pdesc.type() == PropertyDescriptor.GENERIC) {
- final GlobalObject global = (GlobalObject) Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final PropertyDescriptor dDesc = global.newDataDescriptor(UNDEFINED, false, false, false);
dDesc.fillFrom((ScriptObject)pdesc);
@@ -873,8 +867,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter);
}
- notifyPropertyModified(this, oldProperty, newProperty);
-
return modifyOwnProperty(oldProperty, newProperty);
}
@@ -981,17 +973,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
- * Get the object value of a property
- *
- * @param find {@link FindProperty} lookup result
- *
- * @return the value of the property
- */
- protected static Object getObjectValue(final FindProperty find) {
- return find.getObjectValue();
- }
-
- /**
* Return methodHandle of value function for call.
*
* @param find data from find property.
@@ -1001,7 +982,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return value of property as a MethodHandle or null.
*/
protected MethodHandle getCallMethodHandle(final FindProperty find, final MethodType type, final String bindName) {
- return getCallMethodHandle(getObjectValue(find), type, bindName);
+ return getCallMethodHandle(find.getObjectValue(), type, bindName);
}
/**
@@ -1025,7 +1006,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return Value of property.
*/
public final Object getWithProperty(final Property property) {
- return getObjectValue(new FindProperty(this, this, property));
+ return new FindProperty(this, this, property).getObjectValue();
}
/**
@@ -1118,29 +1099,33 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*/
public synchronized final void setProto(final ScriptObject newProto) {
final ScriptObject oldProto = proto;
- map = map.changeProto(oldProto, newProto);
-
- if (newProto != null) {
- newProto.setIsPrototype();
- }
-
- proto = newProto;
- if (isPrototype()) {
- // tell listeners that my __proto__ has been changed
- notifyProtoChanged(this, oldProto, newProto);
+ if (oldProto != newProto) {
+ proto = newProto;
- if (oldProto != null) {
- oldProto.removePropertyListener(this);
- }
-
- if (newProto != null) {
- newProto.addPropertyListener(this);
+ // Let current listeners know that the protototype has changed and set our map
+ final PropertyListeners listeners = getMap().getListeners();
+ if (listeners != null) {
+ listeners.protoChanged();
}
+ // Replace our current allocator map with one that is associated with the new prototype.
+ setMap(getMap().changeProto(newProto));
}
}
/**
+ * Set the initial __proto__ of this object. This should be used instead of
+ * {@link #setProto} if it is known that the current property map will not be
+ * used on a new object with any other parent property map, so we can pass over
+ * property map invalidation/evolution.
+ *
+ * @param initialProto the initial __proto__ to set.
+ */
+ public void setInitialProto(final ScriptObject initialProto) {
+ this.proto = initialProto;
+ }
+
+ /**
* Set the __proto__ of an object with checks.
* @param newProto Prototype to set.
*/
@@ -1160,7 +1145,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
setProto((ScriptObject)newProto);
} else {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
final Object newProtoObject = JSType.toScriptObject(global, newProto);
if (newProtoObject instanceof ScriptObject) {
@@ -1250,11 +1235,11 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return the default value
*/
public Object getDefaultValue(final Class<?> typeHint) {
- // We delegate to GlobalObject, as the implementation uses dynamic call sites to invoke object's "toString" and
+ // We delegate to Global, as the implementation uses dynamic call sites to invoke object's "toString" and
// "valueOf" methods, and in order to avoid those call sites from becoming megamorphic when multiple contexts
// are being executed in a long-running program, we move the code and their associated dynamic call sites
// (Global.TO_STRING and Global.VALUE_OF) into per-context code.
- return ((GlobalObject)Context.getGlobalTrusted()).getDefaultValue(this, typeHint);
+ return Context.getGlobal().getDefaultValue(this, typeHint);
}
/**
@@ -1330,25 +1315,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
- * Check if this object is a prototype
- *
- * @return {@code true} if is prototype
- */
- public final boolean isPrototype() {
- return (flags & IS_PROTOTYPE) != 0;
- }
-
- /**
- * Flag this object as having a prototype.
- */
- public final void setIsPrototype() {
- if (proto != null && !isPrototype()) {
- proto.addPropertyListener(this);
- }
- flags |= IS_PROTOTYPE;
- }
-
- /**
* Check if this object has non-writable length property
*
* @return {@code true} if 'length' property is non-writable
@@ -1712,6 +1678,44 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
+ * Test whether this object contains in its prototype chain or is itself a with-object.
+ * @return true if a with-object was found
+ */
+ final boolean hasWithScope() {
+ if (isScope()) {
+ for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
+ if (obj instanceof WithObject) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add a filter to the first argument of {@code methodHandle} that calls its {@link #getProto()} method
+ * {@code depth} times.
+ * @param methodHandle a method handle
+ * @param depth distance to target prototype
+ * @return the filtered method handle
+ */
+ static MethodHandle addProtoFilter(final MethodHandle methodHandle, final int depth) {
+ if (depth == 0) {
+ return methodHandle;
+ }
+ final int listIndex = depth - 1; // We don't need 0-deep walker
+ MethodHandle filter = listIndex < protoFilters.size() ? protoFilters.get(listIndex) : null;
+
+ if(filter == null) {
+ filter = addProtoFilter(GETPROTO, depth - 1);
+ protoFilters.add(null);
+ protoFilters.set(listIndex, filter);
+ }
+
+ return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
+ }
+
+ /**
* Find the appropriate GET method for an invoke dynamic call.
*
* @param desc the call site descriptor
@@ -1722,18 +1726,14 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*/
protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if (request.isCallSiteUnstable()) {
- return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
+ if (request.isCallSiteUnstable() || hasWithScope()) {
+ return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc));
}
final FindProperty find = findProperty(name, true);
MethodHandle methodHandle;
if (find == null) {
- if (PROTO_PROPERTY_NAME.equals(name)) {
- return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard());
- }
-
if ("getProp".equals(operator)) {
return noSuchProperty(desc, request);
} else if ("getMethod".equals(operator)) {
@@ -1748,40 +1748,43 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final Property property = find.getProperty();
methodHandle = find.getGetter(returnType);
- // getMap() is fine as we have the prototype switchpoint depending on where the property was found
- final MethodHandle guard = NashornGuards.getMapGuard(getMap());
+ // Get the appropriate guard for this callsite and property.
+ final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
+ final ScriptObject owner = find.getOwner();
if (methodHandle != null) {
assert methodHandle.type().returnType().equals(returnType);
if (find.isSelf()) {
- return new GuardedInvocation(methodHandle, ObjectClassGenerator.OBJECT_FIELDS_ONLY &&
- NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard);
+ return new GuardedInvocation(methodHandle, guard);
}
- final ScriptObject prototype = find.getOwner();
-
- if (!property.hasGetterFunction(prototype)) {
- methodHandle = bindTo(methodHandle, prototype);
+ if (!property.hasGetterFunction(owner)) {
+ // Add a filter that replaces the self object with the prototype owning the property.
+ methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
}
- return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard);
+ return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
}
assert !NashornCallSiteDescriptor.isFastScope(desc);
- return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
+ return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
}
- private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
- final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
+ private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
+ final boolean isMethod, final boolean isScope) {
+ final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
return new GuardedInvocation(invoker, guard);
}
@SuppressWarnings("unused")
- private Object megamorphicGet(final String key, final boolean isMethod) {
+ private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
+ }
+ if (isScope) {
+ throw referenceError("not.defined", key);
}
return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
@@ -1824,6 +1827,28 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
+ * Get a switch point for a property with the given {@code name} that will be invalidated when
+ * the property definition is changed in this object's prototype chain. Returns {@code null} if
+ * the property is defined in this object itself.
+ *
+ * @param name the property name
+ * @param owner the property owner, null if property is not defined
+ * @return a SwitchPoint or null
+ */
+ public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
+ if (owner == this || getProto() == null) {
+ return null;
+ }
+
+ for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
+ ScriptObject parent = obj.getProto();
+ parent.getMap().addListener(name, obj.getMap());
+ }
+
+ return getMap().getSwitchPoint(name);
+ }
+
+ /**
* Find the appropriate SET method for an invoke dynamic call.
*
* @param desc the call site descriptor
@@ -1833,7 +1858,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*/
protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if (request.isCallSiteUnstable()) {
+ if (request.isCallSiteUnstable() || hasWithScope()) {
return findMegaMorphicSetMethod(desc, name);
}
@@ -1863,9 +1888,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return createEmptySetMethod(desc, "property.not.writable", true);
}
} else {
- if (PROTO_PROPERTY_NAME.equals(name)) {
- return new GuardedInvocation(SETPROTOCHECK, NashornGuards.getScriptObjectGuard());
- } else if (! isExtensible()) {
+ if (! isExtensible()) {
return createEmptySetMethod(desc, "object.non.extensible", false);
}
}
@@ -1879,8 +1902,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this)));
}
assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
- final PropertyMap myMap = getMap();
- return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap));
+ return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
}
@SuppressWarnings("unused")
@@ -1888,7 +1910,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final ScriptObject obj = (ScriptObject)self;
final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
if (!obj.isExtensible()) {
- throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
+ if (isStrict) {
+ throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
+ }
} else if (obj.compareAndSetMap(oldMap, newMap)) {
setter.invokeExact(self, value);
} else {
@@ -1953,6 +1977,15 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
}
+ @SuppressWarnings("unused")
+ private static Object globalFilter(final Object object) {
+ ScriptObject sobj = (ScriptObject) object;
+ while (sobj != null && !(sobj instanceof Global)) {
+ sobj = sobj.getProto();
+ }
+ return sobj;
+ }
+
private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
@@ -1998,7 +2031,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return noSuchProperty(desc, request);
}
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (! (value instanceof ScriptFunction)) {
return createEmptyGetter(desc, name);
}
@@ -2024,7 +2057,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
if (find != null) {
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
ScriptFunction func = null;
MethodHandle methodHandle = null;
@@ -2038,7 +2071,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
methodHandle = bindTo(methodHandle, UNDEFINED);
}
return new GuardedInvocation(methodHandle,
- find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null,
+ getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
}
}
@@ -2049,16 +2082,17 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return createEmptyGetter(desc, name);
}
+
/**
* Invoke fall back if a property is not found.
* @param name Name of property.
* @return Result from call.
*/
- private Object invokeNoSuchProperty(final String name) {
+ protected Object invokeNoSuchProperty(final String name) {
final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
if (find != null) {
- final Object func = getObjectValue(find);
+ final Object func = find.getObjectValue();
if (func instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)func, this, name);
@@ -2080,7 +2114,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return invokeNoSuchProperty(name);
}
- final Object value = getObjectValue(find);
+ final Object value = find.getObjectValue();
if (! (value instanceof ScriptFunction)) {
return UNDEFINED;
}
@@ -2089,7 +2123,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
- return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
+ return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
+ getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
}
private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
@@ -2170,12 +2205,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
if (fieldCount < fieldMaximum) {
property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
- notifyPropertyAdded(this, property);
property = addOwnProperty(property);
} else {
int i = getMap().getSpillLength();
property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
- notifyPropertyAdded(this, property);
property = addOwnProperty(property);
i = property.getSlot();
@@ -2621,7 +2654,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final FindProperty find = object.findProperty(key, false, false, this);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
}
}
@@ -2639,7 +2672,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
final FindProperty find = findProperty(key, true);
if (find != null) {
- return getObjectValue(find);
+ return find.getObjectValue();
}
}
@@ -2703,9 +2736,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @param strict are we in strict mode
*/
private void doesNotHave(final int index, final Object value, final boolean strict) {
- final long oldLength = getArray().length();
final long longIndex = ArrayIndex.toLongIndex(index);
-
if (getMap().containsArrayKeys()) {
final String key = JSType.toString(longIndex);
final FindProperty find = findProperty(key, true);
@@ -2716,6 +2747,18 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
}
+ setValueAtArrayIndex(longIndex, index, value, strict);
+ }
+
+ /**
+ * Handle when an array doesn't have a slot - possibly grow and/or convert array.
+ *
+ * @param index key as index
+ * @param value element value
+ * @param strict are we in strict mode
+ */
+ private void setValueAtArrayIndex(final long longIndex, final int index, final Object value, final boolean strict) {
+ final long oldLength = getArray().length();
if (longIndex >= oldLength) {
if (!isExtensible()) {
if (strict) {
@@ -2759,7 +2802,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
public final void setObject(final FindProperty find, final boolean strict, final String key, final Object value) {
FindProperty f = find;
- if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
+ if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty) && !isScope()) {
+ // Setting a property should not modify the property in prototype unless this is a scope object.
f = null;
}
@@ -2779,7 +2823,15 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
- spill(key, value);
+ ScriptObject sobj = this;
+ // undefined scope properties are set in the global object.
+ if (isScope()) {
+ while (sobj != null && !(sobj instanceof Global)) {
+ sobj = sobj.getProto();
+ }
+ assert sobj != null : "no parent global object in scope";
+ }
+ sobj.spill(key, value);
}
}
@@ -3228,7 +3280,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
final Property prop = find.getProperty();
- notifyPropertyDeleted(this, prop);
deleteOwnProperty(prop);
return true;
diff --git a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index d9705676..6df047d8 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -474,7 +474,7 @@ public final class ScriptRuntime {
* @return {@link WithObject} that is the new scope
*/
public static ScriptObject openWith(final ScriptObject scope, final Object expression) {
- final ScriptObject global = Context.getGlobalTrusted();
+ final Global global = Context.getGlobal();
if (expression == UNDEFINED) {
throw typeError(global, "cant.apply.with.to.undefined");
} else if (expression == null) {
diff --git a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
index 777254d8..edee3748 100644
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@@ -31,7 +31,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
import jdk.nashorn.internal.runtime.linker.NashornGuards;
@@ -80,7 +79,7 @@ final class SetMethodCreator {
}
/**
- * This class encapsulates the results of looking up a setter method; it's basically a triple of a method hanle,
+ * This class encapsulates the results of looking up a setter method; it's basically a triple of a method handle,
* a Property object, and flags for invocation.
*
*/
@@ -104,21 +103,9 @@ final class SetMethodCreator {
* @return the composed guarded invocation that represents the dynamic setter method for the property.
*/
GuardedInvocation createGuardedInvocation() {
- return new GuardedInvocation(methodHandle, getGuard());
+ return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc));
}
- private MethodHandle getGuard() {
- return needsNoGuard() ? null : NashornGuards.getMapGuard(getMap());
- }
-
- private boolean needsNoGuard() {
- return NashornCallSiteDescriptor.isFastScope(desc) &&
- (ObjectClassGenerator.OBJECT_FIELDS_ONLY || isPropertyTypeStable());
- }
-
- private boolean isPropertyTypeStable() {
- return property == null || !property.canChangeType();
- }
}
private SetMethod createSetMethod() {
@@ -151,10 +138,9 @@ final class SetMethodCreator {
assert methodHandle != null;
assert property != null;
- final ScriptObject prototype = find.getOwner();
final MethodHandle boundHandle;
- if (!property.hasSetterFunction(prototype) && find.isInherited()) {
- boundHandle = ScriptObject.bindTo(methodHandle, prototype);
+ if (!property.hasSetterFunction(find.getOwner()) && find.isInherited()) {
+ boundHandle = ScriptObject.addProtoFilter(methodHandle, find.getProtoChainLength());
} else {
boundHandle = methodHandle;
}
@@ -162,13 +148,16 @@ final class SetMethodCreator {
}
private SetMethod createGlobalPropertySetter() {
- final ScriptObject global = Context.getGlobalTrusted();
- return new SetMethod(ScriptObject.bindTo(global.addSpill(getName()), global), null);
+ final ScriptObject global = Context.getGlobal();
+ return new SetMethod(MH.filterArguments(global.addSpill(getName()), 0, ScriptObject.GLOBALFILTER), null);
}
private SetMethod createNewPropertySetter() {
final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
- sobj.notifyPropertyAdded(sobj, sm.property);
+ final PropertyListeners listeners = map.getListeners();
+ if (listeners != null) {
+ listeners.propertyAdded(sm.property);
+ }
return sm;
}
diff --git a/src/jdk/nashorn/internal/runtime/Source.java b/src/jdk/nashorn/internal/runtime/Source.java
index 0455a86c..f7e890ff 100644
--- a/src/jdk/nashorn/internal/runtime/Source.java
+++ b/src/jdk/nashorn/internal/runtime/Source.java
@@ -27,27 +27,38 @@ package jdk.nashorn.internal.runtime;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
+import java.lang.ref.WeakReference;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
+import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Objects;
+import java.util.WeakHashMap;
+import jdk.nashorn.api.scripting.URLReader;
import jdk.nashorn.internal.parser.Token;
/**
* Source objects track the origin of JavaScript entities.
- *
*/
public final class Source {
+
+ private static final DebugLogger DEBUG = new DebugLogger("source");
+ private static final int BUF_SIZE = 8 * 1024;
+ private static final Cache CACHE = new Cache();
+
/**
* Descriptive name of the source as supplied by the user. Used for error
* reporting to the user. For example, SyntaxError will use this to print message.
@@ -62,49 +73,306 @@ public final class Source {
*/
private final String base;
- /** Cached source content. */
- private final char[] content;
-
- /** Length of source content. */
- private final int length;
+ /** Source content */
+ private final Data data;
/** Cached hash code */
private int hash;
- /** Source URL if available */
- private final URL url;
+ /** Message digest */
+ private byte[] digest;
+
+ // Do *not* make this public, ever! Trusts the URL and content.
+ private Source(final String name, final String base, final Data data) {
+ this.name = name;
+ this.base = base;
+ this.data = data;
+ }
+
+ private static synchronized Source sourceFor(final String name, final String base, final URLData data) throws IOException {
+ try {
+ final Source newSource = new Source(name, base, data);
+ final Source existingSource = CACHE.get(newSource);
+ if (existingSource != null) {
+ // Force any access errors
+ data.checkPermissionAndClose();
+ return existingSource;
+ } else {
+ // All sources in cache must be fully loaded
+ data.load();
+ CACHE.put(newSource, newSource);
+ return newSource;
+ }
+ } catch (RuntimeException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException) cause;
+ }
+ throw e;
+ }
+ }
+
+ private static class Cache extends WeakHashMap<Source, WeakReference<Source>> {
+ public Source get(final Source key) {
+ final WeakReference<Source> ref = super.get(key);
+ return ref == null ? null : ref.get();
+ }
+
+ public void put(final Source key, final Source value) {
+ assert !(value.data instanceof RawData);
+ put(key, new WeakReference<>(value));
+ }
+ }
+
+ // Wrapper to manage lazy loading
+ private static interface Data {
- private static final int BUFSIZE = 8 * 1024;
+ URL url();
- // Do *not* make this public ever! Trusts the URL and content. So has to be called
- // from other public constructors. Note that this can not be some init method as
- // we initialize final fields from here.
- private Source(final String name, final String base, final char[] content, final URL url) {
- this.name = name;
- this.base = base;
- this.content = content;
- this.length = content.length;
- this.url = url;
+ int length();
+
+ long lastModified();
+
+ char[] array();
+ }
+
+ private static class RawData implements Data {
+ private final char[] array;
+ private int hash;
+
+ private RawData(final char[] array) {
+ this.array = Objects.requireNonNull(array);
+ }
+
+ private RawData(final String source) {
+ this.array = Objects.requireNonNull(source).toCharArray();
+ }
+
+ private RawData(final Reader reader) throws IOException {
+ this(readFully(reader));
+ }
+
+ @Override
+ public int hashCode() {
+ int h = hash;
+ if (h == 0) {
+ h = hash = Arrays.hashCode(array);
+ }
+ return h;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RawData) {
+ return Arrays.equals(array, ((RawData)obj).array);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return new String(array());
+ }
+
+ @Override
+ public URL url() {
+ return null;
+ }
+
+ @Override
+ public int length() {
+ return array.length;
+ }
+
+ @Override
+ public long lastModified() {
+ return 0;
+ }
+
+ @Override
+ public char[] array() {
+ return array;
+ }
+
+
+ }
+
+ private static class URLData implements Data {
+ private final URL url;
+ protected final Charset cs;
+ private int hash;
+ protected char[] array;
+ protected int length;
+ protected long lastModified;
+
+ private URLData(final URL url, final Charset cs) {
+ this.url = Objects.requireNonNull(url);
+ this.cs = cs;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = hash;
+ if (h == 0) {
+ h = hash = url.hashCode();
+ }
+ return h;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof URLData)) {
+ return false;
+ }
+
+ URLData otherData = (URLData) other;
+
+ if (url.equals(otherData.url)) {
+ // Make sure both have meta data loaded
+ try {
+ if (isDeferred()) {
+ // Data in cache is always loaded, and we only compare to cached data.
+ assert !otherData.isDeferred();
+ loadMeta();
+ } else if (otherData.isDeferred()) {
+ otherData.loadMeta();
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ // Compare meta data
+ return this.length == otherData.length && this.lastModified == otherData.lastModified;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return new String(array());
+ }
+
+ @Override
+ public URL url() {
+ return url;
+ }
+
+ @Override
+ public int length() {
+ return length;
+ }
+
+ @Override
+ public long lastModified() {
+ return lastModified;
+ }
+
+ @Override
+ public char[] array() {
+ assert !isDeferred();
+ return array;
+ }
+
+ boolean isDeferred() {
+ return array == null;
+ }
+
+ protected void checkPermissionAndClose() throws IOException {
+ try (InputStream in = url.openStream()) {}
+ debug("permission checked for ", url);
+ }
+
+ protected void load() throws IOException {
+ if (array == null) {
+ final URLConnection c = url.openConnection();
+ try (InputStream in = c.getInputStream()) {
+ array = cs == null ? readFully(in) : readFully(in, cs);
+ length = array.length;
+ lastModified = c.getLastModified();
+ debug("loaded content for ", url);
+ }
+ }
+ }
+
+ protected void loadMeta() throws IOException {
+ if (length == 0 && lastModified == 0) {
+ final URLConnection c = url.openConnection();
+ length = c.getContentLength();
+ lastModified = c.getLastModified();
+ debug("loaded metadata for ", url);
+ }
+ }
+ }
+
+ private static class FileData extends URLData {
+ private final File file;
+
+ private FileData(final File file, final Charset cs) {
+ super(getURLFromFile(file), cs);
+ this.file = file;
+
+ }
+
+ @Override
+ protected void checkPermissionAndClose() throws IOException {
+ if (!file.canRead()) {
+ throw new FileNotFoundException(file + " (Permission Denied)");
+ }
+ debug("permission checked for ", file);
+ }
+
+ @Override
+ protected void loadMeta() {
+ if (length == 0 && lastModified == 0) {
+ length = (int) file.length();
+ lastModified = file.lastModified();
+ debug("loaded metadata for ", file);
+ }
+ }
+
+ @Override
+ protected void load() throws IOException {
+ if (array == null) {
+ array = cs == null ? readFully(file) : readFully(file, cs);
+ length = array.length;
+ lastModified = file.lastModified();
+ debug("loaded content for ", file);
+ }
+ }
+ }
+
+ private static void debug(final Object... msg) {
+ DEBUG.info(msg);
+ }
+
+ private char[] data() {
+ return data.array();
}
/**
- * Constructor
+ * Returns an instance
*
* @param name source name
* @param content contents as char array
*/
- public Source(final String name, final char[] content) {
- this(name, baseName(name, null), content, null);
+ public static Source sourceFor(final String name, final char[] content) {
+ return new Source(name, baseName(name), new RawData(content));
}
/**
- * Constructor
+ * Returns an instance
*
* @param name source name
* @param content contents as string
*/
- public Source(final String name, final String content) {
- this(name, content.toCharArray());
+ public static Source sourceFor(final String name, final String content) {
+ return new Source(name, baseName(name), new RawData(content));
}
/**
@@ -115,8 +383,8 @@ public final class Source {
*
* @throws IOException if source cannot be loaded
*/
- public Source(final String name, final URL url) throws IOException {
- this(name, baseURL(url, null), readFully(url), url);
+ public static Source sourceFor(final String name, final URL url) throws IOException {
+ return sourceFor(name, url, null);
}
/**
@@ -128,8 +396,8 @@ public final class Source {
*
* @throws IOException if source cannot be loaded
*/
- public Source(final String name, final URL url, final Charset cs) throws IOException {
- this(name, baseURL(url, null), readFully(url, cs), url);
+ public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException {
+ return sourceFor(name, baseURL(url), new URLData(url, cs));
}
/**
@@ -140,8 +408,8 @@ public final class Source {
*
* @throws IOException if source cannot be loaded
*/
- public Source(final String name, final File file) throws IOException {
- this(name, dirName(file, null), readFully(file), getURLFromFile(file));
+ public static Source sourceFor(final String name, final File file) throws IOException {
+ return sourceFor(name, file, null);
}
/**
@@ -153,8 +421,25 @@ public final class Source {
*
* @throws IOException if source cannot be loaded
*/
- public Source(final String name, final File file, final Charset cs) throws IOException {
- this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file));
+ public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException {
+ final File absFile = file.getAbsoluteFile();
+ return sourceFor(name, dirName(absFile, null), new FileData(file, cs));
+ }
+
+ /**
+ * Returns an instance
+ *
+ * @param name source name
+ * @param reader reader from which source can be loaded
+ * @throws IOException if source cannot be loaded
+ */
+ public static Source sourceFor(final String name, final Reader reader) throws IOException {
+ // Extract URL from URLReader to defer loading and reuse cached data if available.
+ if (reader instanceof URLReader) {
+ final URLReader urlReader = (URLReader) reader;
+ return sourceFor(name, urlReader.getURL(), urlReader.getCharset());
+ }
+ return new Source(name, baseName(name), new RawData(reader));
}
@Override
@@ -162,21 +447,18 @@ public final class Source {
if (this == obj) {
return true;
}
-
if (!(obj instanceof Source)) {
return false;
}
-
- final Source src = (Source)obj;
- // Only compare content as a last resort measure
- return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content);
+ final Source other = (Source) obj;
+ return Objects.equals(name, other.name) && data.equals(other.data);
}
@Override
public int hashCode() {
int h = hash;
if (h == 0) {
- h = hash = Arrays.hashCode(content) ^ Objects.hashCode(name);
+ h = hash = data.hashCode() ^ Objects.hashCode(name);
}
return h;
}
@@ -186,7 +468,7 @@ public final class Source {
* @return Source content.
*/
public String getString() {
- return new String(content, 0, length);
+ return data.toString();
}
/**
@@ -198,6 +480,14 @@ public final class Source {
}
/**
+ * Get the last modified time of this script.
+ * @return Last modified time.
+ */
+ public long getLastModified() {
+ return data.lastModified();
+ }
+
+ /**
* Get the "directory" part of the file or "base" of the URL.
* @return base of file or URL.
*/
@@ -212,7 +502,7 @@ public final class Source {
* @return Source content portion.
*/
public String getString(final int start, final int len) {
- return new String(content, start, len);
+ return new String(data(), start, len);
}
/**
@@ -223,7 +513,7 @@ public final class Source {
public String getString(final long token) {
final int start = Token.descPosition(token);
final int len = Token.descLength(token);
- return new String(content, start, len);
+ return new String(data(), start, len);
}
/**
@@ -233,7 +523,7 @@ public final class Source {
* @return URL source or null
*/
public URL getURL() {
- return url;
+ return data.url();
}
/**
@@ -242,8 +532,9 @@ public final class Source {
* @return Index of first character of line.
*/
private int findBOLN(final int position) {
+ final char[] data = data();
for (int i = position - 1; i > 0; i--) {
- final char ch = content[i];
+ final char ch = data[i];
if (ch == '\n' || ch == '\r') {
return i + 1;
@@ -259,8 +550,10 @@ public final class Source {
* @return Index of last character of line.
*/
private int findEOLN(final int position) {
- for (int i = position; i < length; i++) {
- final char ch = content[i];
+ final char[] data = data();
+ final int length = data.length;
+ for (int i = position; i < length; i++) {
+ final char ch = data[i];
if (ch == '\n' || ch == '\r') {
return i - 1;
@@ -280,11 +573,12 @@ public final class Source {
* @return Line number.
*/
public int getLine(final int position) {
+ final char[] data = data();
// Line count starts at 1.
int line = 1;
for (int i = 0; i < position; i++) {
- final char ch = content[i];
+ final char ch = data[i];
// Works for both \n and \r\n.
if (ch == '\n') {
line++;
@@ -315,7 +609,7 @@ public final class Source {
// Find end of this line.
final int last = findEOLN(position);
- return new String(content, first, last - first + 1);
+ return new String(data(), first, last - first + 1);
}
/**
@@ -323,7 +617,7 @@ public final class Source {
* @return content
*/
public char[] getContent() {
- return content.clone();
+ return data().clone();
}
/**
@@ -331,19 +625,18 @@ public final class Source {
* @return length
*/
public int getLength() {
- return length;
+ return data.length();
}
/**
* Read all of the source until end of file. Return it as char array
*
- * @param reader reader opened to source stream
+ * @param reader reader opened to source stream
* @return source as content
- *
* @throws IOException if source could not be read
*/
public static char[] readFully(final Reader reader) throws IOException {
- final char[] arr = new char[BUFSIZE];
+ final char[] arr = new char[BUF_SIZE];
final StringBuilder sb = new StringBuilder();
try {
@@ -361,9 +654,8 @@ public final class Source {
/**
* Read all of the source until end of file. Return it as char array
*
- * @param file source file
+ * @param file source file
* @return source as content
- *
* @throws IOException if source could not be read
*/
public static char[] readFully(final File file) throws IOException {
@@ -376,10 +668,9 @@ public final class Source {
/**
* Read all of the source until end of file. Return it as char array
*
- * @param file source file
+ * @param file source file
* @param cs Charset used to convert bytes to chars
* @return source as content
- *
* @throws IOException if source could not be read
*/
public static char[] readFully(final File file, final Charset cs) throws IOException {
@@ -388,7 +679,7 @@ public final class Source {
}
final byte[] buf = Files.readAllBytes(file.toPath());
- return (cs != null)? new String(buf, cs).toCharArray() : byteToCharArray(buf);
+ return (cs != null) ? new String(buf, cs).toCharArray() : byteToCharArray(buf);
}
/**
@@ -396,7 +687,6 @@ public final class Source {
*
* @param url URL to read content from
* @return source as content
- *
* @throws IOException if source could not be read
*/
public static char[] readFully(final URL url) throws IOException {
@@ -409,7 +699,6 @@ public final class Source {
* @param url URL to read content from
* @param cs Charset used to convert bytes to chars
* @return source as content
- *
* @throws IOException if source could not be read
*/
public static char[] readFully(final URL url, final Charset cs) throws IOException {
@@ -417,55 +706,85 @@ public final class Source {
}
/**
+ * Get a message digest for this source.
+ *
+ * @return a message digest for this source
+ */
+ public synchronized byte[] getDigest() {
+ if (digest == null) {
+ final char[] content = data();
+ final byte[] bytes = new byte[content.length * 2];
+
+ for (int i = 0; i < content.length; i++) {
+ bytes[i * 2] = (byte) (content[i] & 0x00ff);
+ bytes[i * 2 + 1] = (byte) ((content[i] & 0xff00) >> 8);
+ }
+
+ try {
+ final MessageDigest md = MessageDigest.getInstance("SHA-1");
+ if (name != null) {
+ md.update(name.getBytes(StandardCharsets.UTF_8));
+ }
+ if (base != null) {
+ md.update(base.getBytes(StandardCharsets.UTF_8));
+ }
+ if (getURL() != null) {
+ md.update(getURL().toString().getBytes(StandardCharsets.UTF_8));
+ }
+ digest = md.digest(bytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return digest;
+ }
+
+ /**
* Get the base url. This is currently used for testing only
* @param url a URL
* @return base URL for url
*/
public static String baseURL(final URL url) {
- return baseURL(url, null);
- }
-
- private static String baseURL(final URL url, final String defaultValue) {
if (url.getProtocol().equals("file")) {
try {
final Path path = Paths.get(url.toURI());
final Path parent = path.getParent();
- return (parent != null) ? (parent + File.separator) : defaultValue;
+ return (parent != null) ? (parent + File.separator) : null;
} catch (final SecurityException | URISyntaxException | IOError e) {
- return defaultValue;
+ return null;
}
}
// FIXME: is there a better way to find 'base' URL of a given URL?
String path = url.getPath();
if (path.isEmpty()) {
- return defaultValue;
+ return null;
}
path = path.substring(0, path.lastIndexOf('/') + 1);
final int port = url.getPort();
try {
return new URL(url.getProtocol(), url.getHost(), port, path).toString();
} catch (final MalformedURLException e) {
- return defaultValue;
+ return null;
}
}
- private static String dirName(final File file, final String defaultValue) {
+ private static String dirName(final File file, final String DEFAULT_BASE_NAME) {
final String res = file.getParent();
- return (res != null)? (res + File.separator) : defaultValue;
+ return (res != null) ? (res + File.separator) : DEFAULT_BASE_NAME;
}
// fake directory like name
- private static String baseName(final String name, final String defaultValue) {
+ private static String baseName(final String name) {
int idx = name.lastIndexOf('/');
if (idx == -1) {
idx = name.lastIndexOf('\\');
}
- return (idx != -1)? name.substring(0, idx + 1) : defaultValue;
+ return (idx != -1) ? name.substring(0, idx + 1) : null;
}
private static char[] readFully(final InputStream is, final Charset cs) throws IOException {
- return (cs != null)? new String(readBytes(is), cs).toCharArray() : readFully(is);
+ return (cs != null) ? new String(readBytes(is), cs).toCharArray() : readFully(is);
}
private static char[] readFully(final InputStream is) throws IOException {
@@ -476,19 +795,19 @@ public final class Source {
Charset cs = StandardCharsets.UTF_8;
int start = 0;
// BOM detection.
- if (bytes.length > 1 && bytes[0] == (byte)0xFE && bytes[1] == (byte)0xFF) {
+ if (bytes.length > 1 && bytes[0] == (byte) 0xFE && bytes[1] == (byte) 0xFF) {
start = 2;
cs = StandardCharsets.UTF_16BE;
- } else if (bytes.length > 1 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE) {
+ } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) {
start = 2;
cs = StandardCharsets.UTF_16LE;
- } else if (bytes.length > 2 && bytes[0] == (byte)0xEF && bytes[1] == (byte)0xBB && bytes[2] == (byte)0xBF) {
+ } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
start = 3;
cs = StandardCharsets.UTF_8;
- } else if (bytes.length > 3 && bytes[0] == (byte)0xFF && bytes[1] == (byte)0xFE && bytes[2] == 0 && bytes[3] == 0) {
+ } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) {
start = 4;
cs = Charset.forName("UTF-32LE");
- } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte)0xFE && bytes[3] == (byte)0xFF) {
+ } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) {
start = 4;
cs = Charset.forName("UTF-32BE");
}
@@ -497,7 +816,7 @@ public final class Source {
}
static byte[] readBytes(final InputStream is) throws IOException {
- final byte[] arr = new byte[BUFSIZE];
+ final byte[] arr = new byte[BUF_SIZE];
try {
try (ByteArrayOutputStream buf = new ByteArrayOutputStream()) {
int numBytes;
diff --git a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
index 931d712b..5b21f6ee 100644
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@@ -34,6 +34,7 @@ import jdk.nashorn.internal.lookup.Lookup;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -73,7 +74,7 @@ public final class UserAccessorProperty extends Property {
private static MethodHandle getINVOKE_UA_GETTER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_GETTER,
+ return Context.getGlobal().getDynamicInvoker(INVOKE_UA_GETTER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
@@ -86,7 +87,7 @@ public final class UserAccessorProperty extends Property {
/** Dynamic invoker for setter */
private static Object INVOKE_UA_SETTER = new Object();
private static MethodHandle getINVOKE_UA_SETTER() {
- return ((GlobalObject)Context.getGlobal()).getDynamicInvoker(INVOKE_UA_SETTER,
+ return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
new Callable<MethodHandle>() {
@Override
public MethodHandle call() {
@@ -186,6 +187,11 @@ public final class UserAccessorProperty extends Property {
}
@Override
+ void initMethodHandles(final Class<?> structure) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public ScriptFunction getGetterFunction(final ScriptObject obj) {
final Object value = obj.getSpill(getterSlot);
return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
diff --git a/src/jdk/nashorn/internal/runtime/WithObject.java b/src/jdk/nashorn/internal/runtime/WithObject.java
index 6e03dc60..dc48d727 100644
--- a/src/jdk/nashorn/internal/runtime/WithObject.java
+++ b/src/jdk/nashorn/internal/runtime/WithObject.java
@@ -36,6 +36,7 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.linker.NashornGuards;
/**
* This class supports the handling of scope in a with body.
@@ -87,6 +88,11 @@ public final class WithObject extends ScriptObject implements Scope {
@Override
public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) {
+ if (request.isCallSiteUnstable()) {
+ // Fall back to megamorphic invocation which performs a complete lookup each time without further relinking.
+ return super.lookup(desc, request);
+ }
+
// With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of
// necessity have a Nashorn descriptor - it is safe to cast.
final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
@@ -123,7 +129,7 @@ public final class WithObject extends ScriptObject implements Scope {
}
if (find != null) {
- return fixScopeCallSite(scope.lookup(desc, request), name);
+ return fixScopeCallSite(scope.lookup(desc, request), name, find.getOwner());
}
// the property is not found - now check for
@@ -175,7 +181,7 @@ public final class WithObject extends ScriptObject implements Scope {
link = scope.lookup(desc, request);
if (link != null) {
- return fixScopeCallSite(link, name);
+ return fixScopeCallSite(link, name, null);
}
return null;
@@ -252,13 +258,10 @@ public final class WithObject extends ScriptObject implements Scope {
filterGuard(link, WITHEXPRESSIONFILTER));
}
- private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) {
+ private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER),
- MH.guardWithTest(
- expressionGuard(name),
- filterGuard(newLink, WITHSCOPEFILTER),
- MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class)));
+ NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER)));
}
private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
@@ -267,7 +270,7 @@ public final class WithObject extends ScriptObject implements Scope {
}
private static MethodHandle filter(final MethodHandle mh, final MethodHandle filter) {
- return MH.filterArguments(mh, 0, filter);
+ return MH.filterArguments(mh, 0, filter.asType(filter.type().changeReturnType(mh.type().parameterType(0))));
}
/**
@@ -288,9 +291,9 @@ public final class WithObject extends ScriptObject implements Scope {
return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]);
}
- private MethodHandle expressionGuard(final String name) {
+ private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
final PropertyMap map = expression.getMap();
- final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name);
+ final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index 5c0c0476..58f32968 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -26,7 +26,8 @@
package jdk.nashorn.internal.runtime.arrays;
import java.lang.invoke.MethodHandle;
-import jdk.nashorn.internal.runtime.GlobalObject;
+import java.nio.ByteBuffer;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
@@ -144,6 +145,16 @@ public abstract class ArrayData {
}
/**
+ * Allocate an ArrayData wrapping a given nio ByteBuffer
+ *
+ * @param buf the nio ByteBuffer to wrap
+ * @return the ArrayData
+ */
+ public static ArrayData allocate(final ByteBuffer buf) {
+ return new ByteBufferArrayData((ByteBuffer)buf);
+ }
+
+ /**
* Apply a freeze filter to an ArrayData.
*
* @param underlying the underlying ArrayData to wrap in the freeze filter
@@ -388,7 +399,7 @@ public abstract class ArrayData {
*
* @return property descriptor for element
*/
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), true, true, true);
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
new file mode 100644
index 00000000..33c8679f
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
+import java.nio.ByteBuffer;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Implementation of {@link ArrayData} that wraps a nio ByteBuffer
+ */
+final class ByteBufferArrayData extends ArrayData {
+ private final ByteBuffer buf;
+
+ ByteBufferArrayData(final int length) {
+ super(length);
+ this.buf = ByteBuffer.allocateDirect(length);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param buf ByteBuffer to create array data with.
+ */
+ ByteBufferArrayData(final ByteBuffer buf) {
+ super(buf.capacity());
+ this.buf = buf;
+ }
+
+ /**
+ * Returns property descriptor for element at a given index
+ *
+ * @param global the global object
+ * @param index the index
+ *
+ * @return property descriptor for element
+ */
+ @Override
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
+ // make the index properties not configurable
+ return global.newDataDescriptor(getObject(index), false, true, true);
+ }
+
+ @Override
+ public ArrayData copy() {
+ throw unsupported("copy");
+ }
+
+ @Override
+ public Object[] asObjectArray() {
+ throw unsupported("asObjectArray");
+ }
+
+ @Override
+ public void setLength(final long length) {
+ throw new UnsupportedOperationException("setLength");
+ }
+
+ @Override
+ public void shiftLeft(int by) {
+ throw unsupported("shiftLeft");
+ }
+
+ @Override
+ public ArrayData shiftRight(int by) {
+ throw unsupported("shiftRight");
+ }
+
+ @Override
+ public ArrayData ensure(long safeIndex) {
+ if (safeIndex < buf.capacity()) {
+ return this;
+ }
+
+ throw unsupported("ensure");
+ }
+
+ @Override
+ public ArrayData shrink(long newLength) {
+ throw unsupported("shrink");
+ }
+
+ @Override
+ public ArrayData set(int index, Object value, boolean strict) {
+ if (value instanceof Number) {
+ buf.put(index, ((Number)value).byteValue());
+ return this;
+ }
+
+ throw typeError("not.a.number", ScriptRuntime.safeToString(value));
+ }
+
+ @Override
+ public ArrayData set(int index, int value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(int index, long value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public ArrayData set(int index, double value, boolean strict) {
+ buf.put(index, (byte)value);
+ return this;
+ }
+
+ @Override
+ public int getInt(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ return 0x0ff & buf.get(index);
+ }
+
+ @Override
+ public Object getObject(int index) {
+ return (int)(0x0ff & buf.get(index));
+ }
+
+ @Override
+ public boolean has(int index) {
+ return index > -1 && index < buf.capacity();
+ }
+
+ @Override
+ public boolean canDelete(final int index, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+ return false;
+ }
+
+ @Override
+ public ArrayData delete(int index) {
+ throw unsupported("delete");
+ }
+
+ @Override
+ public ArrayData delete(long fromIndex, long toIndex) {
+ throw unsupported("delete");
+ }
+
+ @Override
+ public ArrayData push(final boolean strict, final Object... items) {
+ throw unsupported("push");
+ }
+
+ @Override
+ public Object pop() {
+ throw unsupported("pop");
+ }
+
+ @Override
+ public ArrayData slice(long from, long to) {
+ throw unsupported("slice");
+ }
+
+ @Override
+ public ArrayData convert(final Class<?> type) {
+ throw unsupported("convert");
+ }
+
+ private UnsupportedOperationException unsupported(final String method) {
+ return new UnsupportedOperationException(method);
+ }
+}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
index a1f772b8..e15541db 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
/**
@@ -44,7 +44,7 @@ final class FrozenArrayFilter extends SealedArrayFilter {
}
@Override
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), false, true, false);
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
index 6f77ddc0..bc6de9f0 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@@ -25,9 +25,9 @@
package jdk.nashorn.internal.runtime.arrays;
+import jdk.nashorn.internal.objects.Global;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import jdk.nashorn.internal.runtime.GlobalObject;
import jdk.nashorn.internal.runtime.PropertyDescriptor;
/**
@@ -62,7 +62,7 @@ class SealedArrayFilter extends ArrayFilter {
}
@Override
- public PropertyDescriptor getDescriptor(final GlobalObject global, final int index) {
+ public PropertyDescriptor getDescriptor(final Global global, final int index) {
return global.newDataDescriptor(getObject(index), false, true, true);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 14d0e14e..6b3acf63 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -131,7 +131,7 @@ import sun.reflect.CallerSensitive;
* implemented securely.
*/
final class JavaAdapterBytecodeGenerator {
- static final Type OBJECT_TYPE = Type.getType(Object.class);
+ static final Type OBJECT_TYPE = Type.getType(Object.class);
static final String OBJECT_TYPE_NAME = OBJECT_TYPE.getInternalName();
@@ -139,6 +139,7 @@ final class JavaAdapterBytecodeGenerator {
static final String GLOBAL_FIELD_NAME = "global";
+ // "global" is declared as Object instead of Global - avoid static references to internal Nashorn classes when possible.
static final String GLOBAL_TYPE_DESCRIPTOR = OBJECT_TYPE.getDescriptor();
static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE);
@@ -318,7 +319,7 @@ final class JavaAdapterBytecodeGenerator {
final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR, false);
final Label initGlobal;
if(samName != null) {
// If the class is a SAM, allow having a ScriptFunction passed as class overrides
@@ -334,7 +335,7 @@ final class JavaAdapterBytecodeGenerator {
if(mi.getName().equals(samName)) {
mv.dup();
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR, false);
} else {
mv.visitInsn(ACONST_NULL);
}
@@ -351,7 +352,7 @@ final class JavaAdapterBytecodeGenerator {
mv.dup();
mv.aconst(mi.getName());
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -368,7 +369,7 @@ final class JavaAdapterBytecodeGenerator {
private static void invokeGetGlobalWithNullCheck(final InstructionAdapter mv) {
invokeGetGlobal(mv);
mv.dup();
- mv.invokevirtual(OBJECT_TYPE_NAME, "getClass", GET_CLASS_METHOD_DESCRIPTOR); // check against null Context
+ mv.invokevirtual(OBJECT_TYPE_NAME, "getClass", GET_CLASS_METHOD_DESCRIPTOR, false); // check against null Context
mv.pop();
}
@@ -425,7 +426,7 @@ final class JavaAdapterBytecodeGenerator {
mv.load(offset, argType);
offset += argType.getSize();
}
- mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor());
+ mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
endInitMethod(mv);
}
@@ -478,7 +479,7 @@ final class JavaAdapterBytecodeGenerator {
mv.load(offset, argType);
offset += argType.getSize();
}
- mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor());
+ mv.invokespecial(superClassName, INIT, originalCtorType.getDescriptor(), false);
// Get a descriptor to the appropriate "JavaAdapterFactory.getHandle" method.
final String getHandleDescriptor = fromFunction ? GET_HANDLE_FUNCTION_DESCRIPTOR : GET_HANDLE_OBJECT_DESCRIPTOR;
@@ -497,7 +498,7 @@ final class JavaAdapterBytecodeGenerator {
mv.aconst(mi.getName());
}
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
}
mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
@@ -521,11 +522,11 @@ final class JavaAdapterBytecodeGenerator {
}
private static void invokeGetGlobal(final InstructionAdapter mv) {
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getGlobal", GET_GLOBAL_METHOD_DESCRIPTOR, false);
}
private static void invokeSetGlobal(final InstructionAdapter mv) {
- mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR);
+ mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "setGlobal", SET_GLOBAL_METHOD_DESCRIPTOR, false);
}
/**
@@ -638,11 +639,11 @@ final class JavaAdapterBytecodeGenerator {
// If the super method is abstract, throw an exception
mv.anew(UNSUPPORTED_OPERATION_TYPE);
mv.dup();
- mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR);
+ mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
mv.athrow();
} else {
// If the super method is not abstract, delegate to it.
- emitSuperCall(mv, name, methodDesc);
+ emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
}
mv.visitLabel(handleDefined);
@@ -671,7 +672,7 @@ final class JavaAdapterBytecodeGenerator {
// stack: [creatingGlobal, creatingGlobal, handle]
// Emit code for switching to the creating global
- // ScriptObject currentGlobal = Context.getGlobal();
+ // Global currentGlobal = Context.getGlobal();
invokeGetGlobal(mv);
mv.dup();
@@ -712,7 +713,7 @@ final class JavaAdapterBytecodeGenerator {
// Invoke the target method handle
final Label tryBlockStart = new Label();
mv.visitLabel(tryBlockStart);
- mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString());
+ mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
final Label tryBlockEnd = new Label();
mv.visitLabel(tryBlockEnd);
emitFinally(mv, currentGlobalVar, globalsDifferVar);
@@ -728,7 +729,7 @@ final class JavaAdapterBytecodeGenerator {
mv.anew(RUNTIME_EXCEPTION_TYPE);
mv.dupX1();
mv.swap();
- mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT, Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE));
+ mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT, Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE), false);
// Fall through to rethrow handler
} else {
throwableHandler = null;
@@ -814,12 +815,12 @@ final class JavaAdapterBytecodeGenerator {
SUPER_PREFIX + name, methodDesc, null, getExceptionNames(method.getExceptionTypes())));
mv.visitCode();
- emitSuperCall(mv, name, methodDesc);
+ emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
endMethod(mv);
}
- private void emitSuperCall(final InstructionAdapter mv, final String name, final String methodDesc) {
+ private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
mv.visitVarInsn(ALOAD, 0);
int nextParam = 1;
final Type methodType = Type.getMethodType(methodDesc);
@@ -827,7 +828,13 @@ final class JavaAdapterBytecodeGenerator {
mv.load(nextParam, t);
nextParam += t.getSize();
}
- mv.invokespecial(superClassName, name, methodDesc);
+
+ // default method - non-abstract, interface method
+ if (Modifier.isInterface(owner.getModifiers())) {
+ mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
+ } else {
+ mv.invokespecial(superClassName, name, methodDesc, false);
+ }
mv.areturn(methodType.getReturnType());
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index c3acb7c5..1b5345b0 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -48,7 +48,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.support.LinkRequestImpl;
-import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.ScriptFunction;
@@ -68,8 +67,8 @@ import jdk.nashorn.internal.runtime.ScriptObject;
* generate the adapter class itself; see its documentation for details about the generated class.
* </p><p>
* You normally don't use this class directly, but rather either create adapters from script using
- * {@link NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
- * {@link NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
+ * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
+ * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
* types.
* </p>
*/
@@ -337,6 +336,7 @@ public final class JavaAdapterFactory {
private static ProtectionDomain createMinimalPermissionDomain() {
// Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
final Permissions permissions = new Permissions();
+ permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.objects"));
permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime"));
permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker"));
return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
index a8e79184..ca3e10c4 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
@@ -29,6 +29,11 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+import java.lang.ref.WeakReference;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -37,10 +42,11 @@ import jdk.nashorn.internal.runtime.ScriptObject;
* Constructor of method handles used to guard call sites.
*/
public final class NashornGuards {
- private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
- private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
- private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
- private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+ private static final MethodHandle IS_SCRIPTOBJECT = findOwnMH("isScriptObject", boolean.class, Object.class);
+ private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
+ private static final MethodHandle IS_MAP = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+ private static final MethodHandle SAME_OBJECT = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
+ private static final MethodHandle IS_INSTANCEOF_2 = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
// don't create me!
private NashornGuards() {
@@ -75,6 +81,55 @@ public final class NashornGuards {
}
/**
+ * Determine whether the given callsite needs a guard.
+ * @param property the property, or null
+ * @param desc the callsite descriptor
+ * @return true if a guard should be used for this callsite
+ */
+ static boolean needsGuard(final Property property, final CallSiteDescriptor desc) {
+ return property == null || property.isConfigurable()
+ || property.isBound() || !ObjectClassGenerator.OBJECT_FIELDS_ONLY
+ || !NashornCallSiteDescriptor.isFastScope(desc) || property.canChangeType();
+ }
+
+ /**
+ * Get the guard for a property access. This returns an identity guard for non-configurable global properties
+ * and a map guard for everything else.
+ *
+ * @param sobj the first object in the prototype chain
+ * @param property the property
+ * @param desc the callsite descriptor
+ * @return method handle for guard
+ */
+ public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc) {
+ if (!needsGuard(property, desc)) {
+ return null;
+ }
+ if (NashornCallSiteDescriptor.isScope(desc)) {
+ if (property != null && property.isBound()) {
+ // This is a declared top level variables in main script or eval, use identity guard.
+ return getIdentityGuard(sobj);
+ }
+ if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) {
+ // Undeclared variables in nested evals need stronger guards
+ return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap()));
+ }
+ }
+ return getMapGuard(sobj.getMap());
+ }
+
+
+ /**
+ * Get a guard that checks referential identity of the current object.
+ *
+ * @param sobj the self object
+ * @return true if same self object instance
+ */
+ public static MethodHandle getIdentityGuard(final ScriptObject sobj) {
+ return MH.insertArguments(SAME_OBJECT, 1, new WeakReference<>(sobj));
+ }
+
+ /**
* Get a guard that checks if in item is an instance of either of two classes.
*
* @param class1 the first class
@@ -85,6 +140,17 @@ public final class NashornGuards {
return MH.insertArguments(IS_INSTANCEOF_2, 1, class1, class2);
}
+ /**
+ * Combine two method handles of type {@code (Object)boolean} using logical AND.
+ *
+ * @param guard1 the first guard
+ * @param guard2 the second guard, only invoked if guard1 returns true
+ * @return true if both guard1 and guard2 returned true
+ */
+ public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) {
+ return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+ }
+
@SuppressWarnings("unused")
private static boolean isScriptObject(final Object self) {
return self instanceof ScriptObject;
@@ -101,6 +167,11 @@ public final class NashornGuards {
}
@SuppressWarnings("unused")
+ private static boolean sameObject(final Object self, final WeakReference<ScriptObject> ref) {
+ return self == ref.get();
+ }
+
+ @SuppressWarnings("unused")
private static boolean isInstanceOf2(final Object self, final Class<?> class1, final Class<?> class2) {
return class1.isInstance(self) || class2.isInstance(self);
}
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
index 5cc1cd2c..22135bc1 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
@@ -37,9 +37,9 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.TypeUtilities;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.GlobalObject;
/**
* Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other
@@ -62,7 +62,7 @@ final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, Gu
final LinkRequest request = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
final Object self = request.getReceiver();
- final GlobalObject global = (GlobalObject) Context.getGlobal();
+ final Global global = Context.getGlobal();
final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor();
return Bootstrap.asType(global.primitiveLookup(request, self), linkerServices, desc);
diff --git a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
index c9b5eaa3..7665be7f 100644
--- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
+++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@@ -35,6 +35,7 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.FindProperty;
import jdk.nashorn.internal.runtime.ScriptObject;
/**
@@ -61,8 +62,9 @@ public final class PrimitiveLookup {
* type {@code receiverClass}.
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass,
- final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) {
- return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter);
+ final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
+ final MethodHandle protoFilter) {
+ return lookupPrimitive(request, Guards.getInstanceOfGuard(receiverClass), wrappedReceiver, wrapFilter, protoFilter);
}
/**
@@ -79,7 +81,8 @@ public final class PrimitiveLookup {
* type (that is implied by both {@code guard} and {@code wrappedReceiver}).
*/
public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard,
- final ScriptObject wrappedReceiver, final MethodHandle wrapFilter) {
+ final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
+ final MethodHandle protoFilter) {
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
if ("setProp".equals(operator) || "setElem".equals(operator)) {
@@ -93,9 +96,23 @@ public final class PrimitiveLookup {
if(desc.getNameTokenCount() > 2) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
- if(wrappedReceiver.findProperty(name, true) == null) {
+ final FindProperty find = wrappedReceiver.findProperty(name, true);
+ if(find == null) {
// Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
return null;
+ } else if (find.isInherited() && !find.getProperty().hasGetterFunction(find.getOwner())) {
+ // If property is found in the prototype object bind the method handle directly to
+ // the proto filter instead of going through wrapper instantiation below.
+ final ScriptObject proto = wrappedReceiver.getProto();
+ final GuardedInvocation link = proto.lookup(desc, request);
+
+ if (link != null) {
+ final MethodHandle invocation = link.getInvocation();
+ final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class));
+ final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter);
+ final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter);
+ return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard));
+ }
}
}
final GuardedInvocation link = wrappedReceiver.lookup(desc, request);
diff --git a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
index 5997ec54..66720c23 100644
--- a/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
@@ -115,7 +115,8 @@ final class ReflectionCheckLinker implements TypeBasedGuardingDynamicLinker{
if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
if(CallSiteDescriptorFactory.tokenizeOperators(desc).contains("getProp")) {
- if ("static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
+ if (desc.getNameTokenCount() > CallSiteDescriptor.NAME_OPERAND &&
+ "static".equals(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND))) {
if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {
// If "getProp:static" passes access checks, allow access.
diff --git a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
index 9250331d..f5158021 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
@@ -46,9 +46,6 @@ public class JdkRegExp extends RegExp {
/** Java regexp pattern to use for match. We compile to one of these */
private Pattern pattern;
- /** The matcher */
- private RegExpMatcher matcher;
-
/**
* Construct a Regular expression from the given {@code source} and {@code flags} strings.
*
@@ -95,14 +92,7 @@ public class JdkRegExp extends RegExp {
return null; // never matches or similar, e.g. a[]
}
- RegExpMatcher currentMatcher = this.matcher;
-
- if (currentMatcher == null || matcher.getInput() != str) {
- currentMatcher = new DefaultMatcher(str);
- this.matcher = currentMatcher;
- }
-
- return currentMatcher;
+ return new DefaultMatcher(str);
}
class DefaultMatcher implements RegExpMatcher {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
index 5ff98ac5..47dbd7c4 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
@@ -44,9 +44,6 @@ public class JoniRegExp extends RegExp {
/** Compiled Joni Regex */
private Regex regex;
- /** Matcher */
- private RegExpMatcher matcher;
-
/**
* Construct a Regular expression from the given {@code pattern} and {@code flags} strings.
*
@@ -95,14 +92,7 @@ public class JoniRegExp extends RegExp {
return null;
}
- RegExpMatcher currentMatcher = this.matcher;
-
- if (currentMatcher == null || input != currentMatcher.getInput()) {
- currentMatcher = new JoniMatcher(input);
- this.matcher = currentMatcher;
- }
-
- return currentMatcher;
+ return new JoniMatcher(input);
}
/**
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
index 360c11eb..91117d1d 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
@@ -131,12 +131,13 @@ public final class Regex implements RegexState {
this.warnings = null;
}
- public void compile() {
+ public synchronized MatcherFactory compile() {
if (factory == null && analyser != null) {
- Compiler compiler = new ArrayCompiler(analyser);
+ new ArrayCompiler(analyser).compile();
analyser = null; // only do this once
- compiler.compile();
}
+ assert factory != null;
+ return factory;
}
public Matcher matcher(char[] chars) {
@@ -144,8 +145,11 @@ public final class Regex implements RegexState {
}
public Matcher matcher(char[] chars, int p, int end) {
- compile();
- return factory.create(this, chars, p, end);
+ MatcherFactory matcherFactory = factory;
+ if (matcherFactory == null) {
+ matcherFactory = compile();
+ }
+ return matcherFactory.create(this, chars, p, end);
}
public WarnCallback getWarnings() {
diff --git a/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index 95993c9f..47248fce 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -78,6 +78,8 @@ type.error.not.a.string={0} is not a String
type.error.not.a.function={0} is not a function
type.error.not.a.constructor={0} is not a constructor function
type.error.not.a.file={0} is not a File
+type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
+type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
# operations not permitted on undefined
type.error.cant.call.undefined=Cannot call undefined
@@ -136,6 +138,9 @@ type.error.no.method.matches.args=Can not invoke method {0} with the passed argu
type.error.method.not.constructor=Java method {0} can't be used as a constructor.
type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
+
+range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor
+range.error.dataview.offset=Offset is outside the bounds of the DataView
range.error.inappropriate.array.length=inappropriate array length: {0}
range.error.inappropriate.array.buffer.length=inappropriate array buffer length: {0}
range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
diff --git a/src/jdk/nashorn/internal/runtime/resources/Options.properties b/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 27262111..9262a401 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -102,6 +102,13 @@ nashorn.option.compile.only = { \
type=Boolean \
}
+nashorn.option.const.as.var = { \
+ name="--const-as-var", \
+ is_undocumented=true, \
+ desc="Replace 'const' with 'var'.", \
+ type=Boolean \
+}
+
nashorn.option.d = { \
name="--dump-debug-dir", \
short_name="-d", \
@@ -230,6 +237,14 @@ nashorn.option.parse.only = { \
desc="Parse without compiling." \
}
+nashorn.option.persistent.code.cache = { \
+ name="--persistent-code-cache", \
+ short_name="-pcc", \
+ desc="Enable disk cache for compiled scripts.", \
+ is_undocumented=true, \
+ default=false \
+}
+
nashorn.option.profile.callsites = { \
name="--profile-callsites", \
short_name="-pcs", \
diff --git a/src/jdk/nashorn/internal/scripts/JO.java b/src/jdk/nashorn/internal/scripts/JO.java
index f2f00062..d6173918 100644
--- a/src/jdk/nashorn/internal/scripts/JO.java
+++ b/src/jdk/nashorn/internal/scripts/JO.java
@@ -33,7 +33,7 @@ import jdk.nashorn.internal.runtime.ScriptObject;
*/
public class JO extends ScriptObject {
- private static final PropertyMap map$ = PropertyMap.newMap().setIsShared();
+ private static final PropertyMap map$ = PropertyMap.newMap();
/**
* Returns the initial property map to be used.
diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java
index ad19484c..33e0afd7 100644
--- a/src/jdk/nashorn/tools/Shell.java
+++ b/src/jdk/nashorn/tools/Shell.java
@@ -25,6 +25,8 @@
package jdk.nashorn.tools;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@@ -42,6 +44,7 @@ import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
@@ -49,7 +52,6 @@ import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;
@@ -148,7 +150,7 @@ public class Shell {
return COMMANDLINE_ERROR;
}
- final ScriptObject global = context.createGlobal();
+ final Global global = context.createGlobal();
final ScriptEnvironment env = context.getEnv();
final List<String> files = env.getFiles();
if (files.isEmpty()) {
@@ -231,8 +233,8 @@ public class Shell {
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private static int compileScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private static int compileScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
final ScriptEnvironment env = context.getEnv();
try {
@@ -243,7 +245,7 @@ public class Shell {
// For each file on the command line.
for (final String fileName : files) {
- final FunctionNode functionNode = new Parser(env, new Source(fileName, new File(fileName)), errors).parse();
+ final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse();
if (errors.getNumberOfErrors() != 0) {
return COMPILATION_ERROR;
@@ -281,8 +283,8 @@ public class Shell {
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private int runScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private int runScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
if (globalChanged) {
@@ -301,7 +303,7 @@ public class Shell {
}
final File file = new File(fileName);
- final ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
+ final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global);
if (script == null || errors.getNumberOfErrors() != 0) {
return COMPILATION_ERROR;
}
@@ -339,8 +341,8 @@ public class Shell {
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private static int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ private static int runFXScripts(final Context context, final Global global, final List<String> files) throws IOException {
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
if (globalChanged) {
@@ -389,11 +391,11 @@ public class Shell {
* @return return code
*/
@SuppressWarnings("resource")
- private static int readEvalPrint(final Context context, final ScriptObject global) {
+ private static int readEvalPrint(final Context context, final Global global) {
final String prompt = bundle.getString("shell.prompt");
final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
final PrintWriter err = context.getErr();
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
final ScriptEnvironment env = context.getEnv();
@@ -404,7 +406,7 @@ public class Shell {
// initialize with "shell.js" script
try {
- final Source source = new Source("<shell.js>", Shell.class.getResource("resources/shell.js"));
+ final Source source = sourceFor("<shell.js>", Shell.class.getResource("resources/shell.js"));
context.eval(global, source.getString(), global, "<shell.js>", false);
} catch (final Exception e) {
err.println(e);
@@ -451,7 +453,7 @@ public class Shell {
}
} finally {
if (globalChanged) {
- Context.setGlobal(global);
+ Context.setGlobal(oldGlobal);
}
}
diff --git a/test/script/basic/JDK-8008448.js b/test/script/basic/JDK-8008448.js
index b30e3417..240efd61 100644
--- a/test/script/basic/JDK-8008448.js
+++ b/test/script/basic/JDK-8008448.js
@@ -26,6 +26,7 @@
* Ensure that all parseable files can be parsed using parser API.
*
* @test
+ * @option --const-as-var
* @option -scripting
* @run
*/
diff --git a/test/script/basic/JDK-8011964.js b/test/script/basic/JDK-8011964.js
new file mode 100644
index 00000000..a46023eb
--- /dev/null
+++ b/test/script/basic/JDK-8011964.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8011964: need indexed access to externally-managed ByteBuffer
+ *
+ * @test
+ * @run
+ */
+
+
+var ByteBuffer = Java.type("java.nio.ByteBuffer");
+var buf = ByteBuffer.allocate(5);
+
+var obj = {}
+Object.setIndexedPropertiesToExternalArrayData(obj, buf);
+
+obj[0] = 'A'.charCodeAt(0);
+obj[1] = 'B'.charCodeAt(0);
+obj[2] = 'C'.charCodeAt(0);
+obj[3] = 'D'.charCodeAt(0);
+obj[4] = 'E'.charCodeAt(0);
+
+for (var i = 0; i < buf.capacity(); i++) {
+ print("obj[" + i + "] = " + obj[i]);
+ print("buf.get(" + i + ") = " + buf.get(i));
+}
+
+var arr = [];
+Object.setIndexedPropertiesToExternalArrayData(arr, buf);
+obj[0] = 'a'.charCodeAt(0);
+obj[1] = 'b'.charCodeAt(0);
+obj[2] = 'c'.charCodeAt(0);
+obj[3] = 'd'.charCodeAt(0);
+obj[4] = 'e'.charCodeAt(0);
+
+for (var i in arr) {
+ print("arr[" + i + "] = " + arr[i]);
+ print("buf.get(" + i + ") = " + buf.get(i));
+}
diff --git a/test/script/basic/JDK-8011964.js.EXPECTED b/test/script/basic/JDK-8011964.js.EXPECTED
new file mode 100644
index 00000000..5bec2bdf
--- /dev/null
+++ b/test/script/basic/JDK-8011964.js.EXPECTED
@@ -0,0 +1,20 @@
+obj[0] = 65
+buf.get(0) = 65
+obj[1] = 66
+buf.get(1) = 66
+obj[2] = 67
+buf.get(2) = 67
+obj[3] = 68
+buf.get(3) = 68
+obj[4] = 69
+buf.get(4) = 69
+arr[0] = 97
+buf.get(0) = 97
+arr[1] = 98
+buf.get(1) = 98
+arr[2] = 99
+buf.get(2) = 99
+arr[3] = 100
+buf.get(3) = 100
+arr[4] = 101
+buf.get(4) = 101
diff --git a/test/script/basic/JDK-8024120.js b/test/script/basic/JDK-8024120.js
index 0ac4ff98..d2913d52 100644
--- a/test/script/basic/JDK-8024120.js
+++ b/test/script/basic/JDK-8024120.js
@@ -32,10 +32,6 @@ var obj = {};
obj.__proto__ = null;
-if (obj.__proto__ !== null || typeof(obj.__proto__) != 'object') {
- fail("obj.__proto__ is expected to be null");
-}
-
var p = Object.getPrototypeOf(obj);
if (p !== null || typeof(p) != 'object') {
fail("Object.getPrototypeOf(obj) is expected to be null");
diff --git a/test/script/basic/JDK-8024174.js b/test/script/basic/JDK-8024174.js
index 5fd48e17..bd9206a6 100644
--- a/test/script/basic/JDK-8024174.js
+++ b/test/script/basic/JDK-8024174.js
@@ -46,6 +46,6 @@ var obj2 = {
__proto__: null
};
-if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) {
+if (Object.getPrototypeOf(obj2) !== null) {
fail("obj2.__proto__ was not set to null inside literal");
}
diff --git a/test/script/basic/JDK-8025515.js b/test/script/basic/JDK-8025515.js
index f3d7cee4..29574d2a 100644
--- a/test/script/basic/JDK-8025515.js
+++ b/test/script/basic/JDK-8025515.js
@@ -30,13 +30,23 @@
// Make sure synthetic names of anonymous functions have correct line numbers
+function getFirstScriptFrame(stack) {
+ for (frameNum in stack) {
+ var frame = stack[frameNum];
+ if (frame.className.startsWith("jdk.nashorn.internal.scripts.Script$")) {
+ return frame;
+ }
+ }
+}
+
function testMethodName(f, expected) {
try {
f();
fail("expected error");
} catch (e) {
- var stack = e.getStackTrace();
- if (stack[0].methodName !== expected) {
+ var stack = e.nashornException.getStackTrace();
+ var name = getFirstScriptFrame(stack).methodName;
+ if (name !== expected) {
fail("got " + stack[0].methodName + ", expected " + expected);
}
}
@@ -44,15 +54,15 @@ function testMethodName(f, expected) {
testMethodName(function() {
return a.b.c;
-}, "_L45");
+}, "L:55");
-testMethodName(function() { throw new Error() }, "_L49");
+testMethodName(function() { throw new Error() }, "L:59");
var f = (function() {
return function() { a.b.c; };
})();
-testMethodName(f, "_L51$_L52");
+testMethodName(f, "L:61$L:62");
testMethodName((function() {
return function() { return a.b.c; };
-})(), "_L56$_L57");
+})(), "L:66$L:67");
diff --git a/test/script/basic/JDK-8026161.js b/test/script/basic/JDK-8026161.js
index 49f888b7..e3e88486 100644
--- a/test/script/basic/JDK-8026161.js
+++ b/test/script/basic/JDK-8026161.js
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,5 +28,5 @@
* @run
*/
-print(new java.awt.Color(1, 1, 1)) // creates Color[r=1,g=1,b=1]
-print(new java.awt.Color(1.0, 1.0, 1.0)) // Color[r=255,g=255,b=255]
+print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1))
+print(Java.type("jdk.nashorn.test.models.IntFloatOverloadSelection").overloadedMethod(1.0))
diff --git a/test/script/basic/JDK-8026161.js.EXPECTED b/test/script/basic/JDK-8026161.js.EXPECTED
index c7b00b08..ac032cff 100644
--- a/test/script/basic/JDK-8026161.js.EXPECTED
+++ b/test/script/basic/JDK-8026161.js.EXPECTED
@@ -1,2 +1,2 @@
-java.awt.Color[r=1,g=1,b=1]
-java.awt.Color[r=255,g=255,b=255]
+int
+float
diff --git a/test/script/basic/JDK-8027933.js b/test/script/basic/JDK-8027933.js
new file mode 100644
index 00000000..506abc23
--- /dev/null
+++ b/test/script/basic/JDK-8027933.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8027933: Add const.as.var option
+ *
+ * @test
+ * @option --const-as-var
+ * @run
+ */
+
+const THE_ANSWER = 42;
+print("Answer to all questions: " + THE_ANSWER);
+
+print((function () {
+ const FORTY_TWO = 42;
+ return FORTY_TWO
+})())
diff --git a/test/script/basic/JDK-8027933.js.EXPECTED b/test/script/basic/JDK-8027933.js.EXPECTED
new file mode 100644
index 00000000..cb920ab6
--- /dev/null
+++ b/test/script/basic/JDK-8027933.js.EXPECTED
@@ -0,0 +1,2 @@
+Answer to all questions: 42
+42
diff --git a/test/script/basic/JDK-8029364.js b/test/script/basic/JDK-8029364.js
new file mode 100644
index 00000000..dfa8ea9d
--- /dev/null
+++ b/test/script/basic/JDK-8029364.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8029364: NashornException to expose thrown object
+ *
+ * @test
+ * @run
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+var g = e.eval("this");
+try {
+ e.eval("var e = new Error('foo'); e.bar = 33; throw e");
+} catch (se) {
+ // ScriptException instance's cause is a NashornException
+ print(se.getClass());
+ var cause = se.cause;
+ print(cause.getClass());
+ // NashornException instance has 'ecmaError' bean getter
+ print(cause.ecmaError);
+ // access to underlying ECMA Error object
+ print(cause.ecmaError instanceof g.Error);
+ print(cause.ecmaError.name);
+ print(cause.ecmaError.message);
+ print(cause.ecmaError.bar);
+}
+
diff --git a/test/script/basic/JDK-8029364.js.EXPECTED b/test/script/basic/JDK-8029364.js.EXPECTED
new file mode 100644
index 00000000..d01bb9ee
--- /dev/null
+++ b/test/script/basic/JDK-8029364.js.EXPECTED
@@ -0,0 +1,7 @@
+class javax.script.ScriptException
+class jdk.nashorn.internal.runtime.ECMAException
+Error: foo
+true
+Error
+foo
+33
diff --git a/test/script/basic/JDK-8029667.js b/test/script/basic/JDK-8029667.js
new file mode 100644
index 00000000..c0c2d156
--- /dev/null
+++ b/test/script/basic/JDK-8029667.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8029667: Prototype linking is incorrect
+ *
+ * @test
+ * @run
+ */
+
+function f(x) {
+ return (function inner() {
+ var y; (function dummy() { return y })() // force own scope for the inner function
+ with({}) { // 'with' block turns off fast scopes
+ return x
+ }
+ })();
+}
+print(f(1));
+print(f(2));
+
+function g(x) {
+ (function inner() {
+ var y; (function dummy() { return y })() // force own scope for the inner function
+ with({}) { // 'with' block turns off fast scopes
+ // Test setter as well as getter
+ x = x + 2;
+ }
+ })();
+ print(x);
+}
+
+g(1);
+g(2);
+
+var withScopes = [{ func: function() { print("called 1");} }, { func: function() { print("called 2");} }];
+
+for(var i in withScopes) {
+ with (withScopes[i]) {
+ var main = function() {
+ var frame; // <---- this local variable caused scope to be not set properly prior to fix
+
+ function callFunc() {
+ frame = func();
+ }
+
+ callFunc();
+ }
+ }
+ main();
+}
+
+for(var i in withScopes) {
+ with (withScopes[i]) {
+ var main = function() {
+ var frame; // <---- this local variable caused scope to be not set properly prior to fix
+
+ function callFunc() {
+ frame = func = i;
+ }
+
+ callFunc();
+ }
+ }
+ main();
+}
+
+print(withScopes[0].func);
+print(withScopes[1].func);
+
+
diff --git a/test/script/basic/JDK-8029667.js.EXPECTED b/test/script/basic/JDK-8029667.js.EXPECTED
new file mode 100644
index 00000000..8aa78efe
--- /dev/null
+++ b/test/script/basic/JDK-8029667.js.EXPECTED
@@ -0,0 +1,8 @@
+1
+2
+3
+4
+called 1
+called 2
+0
+1
diff --git a/test/script/basic/JDK-8030182.js b/test/script/basic/JDK-8030182.js
new file mode 100644
index 00000000..f3c492d4
--- /dev/null
+++ b/test/script/basic/JDK-8030182.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8030182: scopeCall with -1 as line number
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ throw new Error("Strange...");
+}
+
+var f2 = func;
+var f3 = func;
+var f4 = func;
+var f5 = func;
+
+// check that "scopeCall" or some such internal method
+// does not appear in script stack trace.
+try {
+ func();
+} catch(err) {
+ print(err.stack.replace(/\\/g, '/'));
+}
diff --git a/test/script/basic/JDK-8030182.js.EXPECTED b/test/script/basic/JDK-8030182.js.EXPECTED
new file mode 100644
index 00000000..d12b6d7f
--- /dev/null
+++ b/test/script/basic/JDK-8030182.js.EXPECTED
@@ -0,0 +1,3 @@
+Error: Strange...
+ at func (test/script/basic/JDK-8030182.js:32)
+ at <program> (test/script/basic/JDK-8030182.js:43)
diff --git a/test/script/basic/JDK-8030182_2.js b/test/script/basic/JDK-8030182_2.js
new file mode 100644
index 00000000..de507e1d
--- /dev/null
+++ b/test/script/basic/JDK-8030182_2.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8030182: scopeCall with -1 as line number
+ *
+ * @test
+ * @run
+ */
+
+var str = "";
+
+// large code to force splitting
+for (i = 0; i < 1000; ++i)
+ str +="o = new Object()\n";
+
+str +="g()";
+
+// check that "$split" or some such internal method
+// does not appear in script stack trace!!
+try {
+ eval(str);
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
diff --git a/test/script/basic/JDK-8030182_2.js.EXPECTED b/test/script/basic/JDK-8030182_2.js.EXPECTED
new file mode 100644
index 00000000..772e504d
--- /dev/null
+++ b/test/script/basic/JDK-8030182_2.js.EXPECTED
@@ -0,0 +1,3 @@
+ReferenceError: "g" is not defined
+ at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@0:-1)
+ at <program> (test/script/basic/JDK-8030182_2.js:42)
diff --git a/test/script/basic/JDK-8030197.js b/test/script/basic/JDK-8030197.js
new file mode 100644
index 00000000..366d33df
--- /dev/null
+++ b/test/script/basic/JDK-8030197.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * JDK-8030197: Nashorn: Object.defineProperty() can be lured to change fixed NaN property
+ *
+ * @test
+ * @run
+ */
+
+function str(n) {
+ var a = new Uint8Array(new Float64Array([n]).buffer);
+ return Array.apply(null, a).reduceRight(
+ function(acc, v){
+ return acc + (v < 10 ? "0" : "") + v.toString(16);
+ }, "");
+}
+
+var o = Object.defineProperty({}, "NaN", { value: NaN })
+var str1 = str(o.NaN);
+Object.defineProperty(o, "NaN", { value: 0/0 })
+var str2 = str(o.NaN);
+if (str1 != str2) {
+ fail("NaN bit pattern changed");
+}
diff --git a/test/script/basic/JDK-8030199.js b/test/script/basic/JDK-8030199.js
new file mode 100644
index 00000000..b6d32fb1
--- /dev/null
+++ b/test/script/basic/JDK-8030199.js
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8030199: Nashorn: Uint8ClampedArray - Incorrect ToUint8Clamp implementation
+ *
+ * @test
+ * @run
+ */
+
+function testTypedArray(ArrayType) {
+ print(ArrayType.BYTES_PER_ELEMENT);
+ var a = new ArrayType(7);
+ a[0] = 4294967296;
+ a[1] = -4294967295;
+ a[2] = 4294967298;
+ a[3] = -4294967298;
+ a[4] = Infinity;
+ a[5] = -Infinity;
+ a[6] = NaN;
+ print(Array.prototype.join.call(a));
+}
+
+testTypedArray(Uint8ClampedArray);
+testTypedArray(Uint8Array);
+testTypedArray(Int8Array);
+testTypedArray(Uint16Array);
+testTypedArray(Int16Array);
+testTypedArray(Uint32Array);
+testTypedArray(Int32Array);
diff --git a/test/script/basic/JDK-8030199.js.EXPECTED b/test/script/basic/JDK-8030199.js.EXPECTED
new file mode 100644
index 00000000..0b2cf627
--- /dev/null
+++ b/test/script/basic/JDK-8030199.js.EXPECTED
@@ -0,0 +1,14 @@
+1
+255,0,255,0,255,0,0
+1
+0,1,2,254,0,0,0
+1
+0,1,2,-2,0,0,0
+2
+0,1,2,65534,0,0,0
+2
+0,1,2,-2,0,0,0
+4
+0,1,2,4294967294,0,0,0
+4
+0,1,2,-2,0,0,0
diff --git a/test/script/basic/JDK-8030200.js b/test/script/basic/JDK-8030200.js
new file mode 100644
index 00000000..e49eec7d
--- /dev/null
+++ b/test/script/basic/JDK-8030200.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8030200: Wrong result for Number.prototype.toString() for certain radix/inputs
+ *
+ * @test
+ * @run
+ */
+
+var n = 0x8000000000000800;
+print(n);
+var s = n.toString(5);
+var m = parseInt(s, 5);
+print(m === n);
+print(n);
diff --git a/test/script/basic/JDK-8030200.js.EXPECTED b/test/script/basic/JDK-8030200.js.EXPECTED
new file mode 100644
index 00000000..38b73bc2
--- /dev/null
+++ b/test/script/basic/JDK-8030200.js.EXPECTED
@@ -0,0 +1,3 @@
+9223372036854778000
+true
+9223372036854778000
diff --git a/test/script/basic/JDK-8030809.js b/test/script/basic/JDK-8030809.js
new file mode 100644
index 00000000..01c7687c
--- /dev/null
+++ b/test/script/basic/JDK-8030809.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8030809: Anonymous functions should not be shown with internal names in script stack trace
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+ (function() {
+ throw new Error();
+ })();
+}
+
+try {
+ func();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
diff --git a/test/script/basic/JDK-8030809.js.EXPECTED b/test/script/basic/JDK-8030809.js.EXPECTED
new file mode 100644
index 00000000..6d2ee69b
--- /dev/null
+++ b/test/script/basic/JDK-8030809.js.EXPECTED
@@ -0,0 +1,4 @@
+Error
+ at <anonymous> (test/script/basic/JDK-8030809.js:33)
+ at func (test/script/basic/JDK-8030809.js:32)
+ at <program> (test/script/basic/JDK-8030809.js:38)
diff --git a/test/script/basic/JDK-8031317.js b/test/script/basic/JDK-8031317.js
new file mode 100644
index 00000000..240a6337
--- /dev/null
+++ b/test/script/basic/JDK-8031317.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8031317: SyntaxError when property setter has no parameter
+ *
+ * @test
+ * @run
+ */
+
+var obj = {
+ get toto() {
+ print("in getter for 'toto'");
+ },
+ set toto() {
+ print("in setter for 'toto'");
+ }
+}
+
+obj.toto;
+obj.toto = 344;
diff --git a/test/script/basic/JDK-8031317.js.EXPECTED b/test/script/basic/JDK-8031317.js.EXPECTED
new file mode 100644
index 00000000..dda72eae
--- /dev/null
+++ b/test/script/basic/JDK-8031317.js.EXPECTED
@@ -0,0 +1,2 @@
+in getter for 'toto'
+in setter for 'toto'
diff --git a/test/script/basic/JDK-8031359.js b/test/script/basic/JDK-8031359.js
new file mode 100644
index 00000000..278fd7d2
--- /dev/null
+++ b/test/script/basic/JDK-8031359.js
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8031359: Invocable.getInterface() works incorrectly if interface has default methods
+ *
+ * @test
+ * @run
+ */
+
+var func = new java.util.function.Function() {
+ apply: function(arg) {
+ print("func called with " + arg);
+ return arg.toUpperCase();
+ }
+};
+
+// Function.andThen is a default method
+func.andThen(func)("hello");
+
+// Function.compose is another default method
+func.compose(new java.util.function.Function() {
+ apply: function(arg) {
+ print("compose called with " + arg);
+ return arg.charAt(0);
+ }
+})("hello");
+
+var func2 = new java.util.function.Function() {
+ apply: function(arg) {
+ print("I am func2: " + arg);
+ return arg;
+ },
+
+ andThen: function(func) {
+ print("This is my andThen!");
+ return func;
+ }
+};
+
+func2.apply("hello");
+func2.andThen(func);
diff --git a/test/script/basic/JDK-8031359.js.EXPECTED b/test/script/basic/JDK-8031359.js.EXPECTED
new file mode 100644
index 00000000..3fb72f1b
--- /dev/null
+++ b/test/script/basic/JDK-8031359.js.EXPECTED
@@ -0,0 +1,6 @@
+func called with hello
+func called with HELLO
+compose called with hello
+func called with h
+I am func2: hello
+This is my andThen!
diff --git a/test/script/basic/JDK-8031715.js b/test/script/basic/JDK-8031715.js
new file mode 100644
index 00000000..19994f51
--- /dev/null
+++ b/test/script/basic/JDK-8031715.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8031715: Indexed access to java package not working
+ * @test
+ * @run
+ */
+
+print(java["net"]);
+print(java["net"]["URL"]);
+print(java["net"].URL);
+print(java.net["URL"]);
+
+var is = "InputStream";
+var io = "io";
+
+print(java.io[is]);
+print(java[io]);
+print(java[io][is]);
+
+var ji = new JavaImporter(java.util, java.io);
+print(ji["InputStream"]);
+print(ji['Vector']);
+
+var hash = "Hashtable";
+var printStream = "PrintStream";
+print(ji[hash]);
+print(ji[printStream]);
diff --git a/test/script/basic/JDK-8031715.js.EXPECTED b/test/script/basic/JDK-8031715.js.EXPECTED
new file mode 100644
index 00000000..1a71de34
--- /dev/null
+++ b/test/script/basic/JDK-8031715.js.EXPECTED
@@ -0,0 +1,11 @@
+[JavaPackage java.net]
+[JavaClass java.net.URL]
+[JavaClass java.net.URL]
+[JavaClass java.net.URL]
+[JavaClass java.io.InputStream]
+[JavaPackage java.io]
+[JavaClass java.io.InputStream]
+[JavaClass java.io.InputStream]
+[JavaClass java.util.Vector]
+[JavaClass java.util.Hashtable]
+[JavaClass java.io.PrintStream]
diff --git a/test/script/basic/JDK-8031983.js b/test/script/basic/JDK-8031983.js
new file mode 100644
index 00000000..f0bfca13
--- /dev/null
+++ b/test/script/basic/JDK-8031983.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8031983: Error objects should capture stack at the constructor
+ *
+ * @test
+ * @run
+ */
+
+var e = new Error();
+print("hello");
+
+try {
+ throw e;
+} catch (e) {
+ print(e.lineNumber);
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+Error.captureStackTrace(e);
+try {
+ throw e;
+} catch (e) {
+ print(e.lineNumber);
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+var obj = {};
+Error.captureStackTrace(obj);
+try {
+ throw obj;
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
diff --git a/test/script/basic/JDK-8031983.js.EXPECTED b/test/script/basic/JDK-8031983.js.EXPECTED
new file mode 100644
index 00000000..9d62db31
--- /dev/null
+++ b/test/script/basic/JDK-8031983.js.EXPECTED
@@ -0,0 +1,9 @@
+hello
+35
+Error
+ at <program> (test/script/basic/JDK-8031983.js:31)
+43
+Error
+ at <program> (test/script/basic/JDK-8031983.js:41)
+[object Object]
+ at <program> (test/script/basic/JDK-8031983.js:50)
diff --git a/test/script/basic/JDK-8032004.js b/test/script/basic/JDK-8032004.js
new file mode 100644
index 00000000..2995566c
--- /dev/null
+++ b/test/script/basic/JDK-8032004.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8032004: instance property "message" of Error objects should be non-enumerable
+ *
+ * @test
+ * @run
+ */
+
+function check(obj) {
+ if (obj.propertyIsEnumerable("message")) {
+ fail(obj.name + " object's message property is enumerable!");
+ }
+}
+
+check(new Error("test"));
+check(new EvalError("test"));
+check(new RangeError("test"));
+check(new ReferenceError("test"));
+check(new SyntaxError("test"));
+check(new TypeError("test"));
+check(new URIError("test"));
diff --git a/test/script/basic/JDK-8032068.js b/test/script/basic/JDK-8032068.js
new file mode 100644
index 00000000..570789d7
--- /dev/null
+++ b/test/script/basic/JDK-8032068.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8032068: implement @sourceURL and #sourceURL directives.
+ *
+ * @test
+ * @run
+ */
+
+
+try {
+ Function("throw new Error();\n//# sourceURL=foo.js")();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+try {
+ eval("function g() { throw Error('x');\n } g();\n//# sourceURL=bar.js");
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+// check @sourceURL for compatibility
+try {
+ Function("throw new Error();\n//@ sourceURL=foo2.js")();
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
+try {
+ eval("function g() { throw Error('x');\n } g();\n//@ sourceURL=bar2.js");
+} catch (e) {
+ print(e.stack.replace(/\\/g, '/'));
+}
+
diff --git a/test/script/basic/JDK-8032068.js.EXPECTED b/test/script/basic/JDK-8032068.js.EXPECTED
new file mode 100644
index 00000000..b8891eee
--- /dev/null
+++ b/test/script/basic/JDK-8032068.js.EXPECTED
@@ -0,0 +1,14 @@
+Error
+ at <anonymous> (foo.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:33)
+Error: x
+ at g (bar.js:1)
+ at <program> (bar.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:39)
+Error
+ at <anonymous> (foo2.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:46)
+Error: x
+ at g (bar2.js:1)
+ at <program> (bar2.js:2)
+ at <program> (test/script/basic/JDK-8032068.js:52)
diff --git a/test/script/basic/JDK-8034055.js b/test/script/basic/JDK-8034055.js
new file mode 100644
index 00000000..0a21d9f9
--- /dev/null
+++ b/test/script/basic/JDK-8034055.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8034055: delete on global object not properly guarded
+ *
+ * @test
+ * @run
+ */
+
+
+var global = this;
+var x;
+
+function test(defineGlobals) {
+ if (defineGlobals) {
+ global.x = 1;
+ global.y = 2;
+ }
+ try {
+ print(x);
+ print(y);
+ } catch (e) {
+ print(e);
+ } finally {
+ print(delete global.x);
+ print(delete global.y);
+ }
+}
+
+// Repeatedly set and delete global variables
+test(true);
+test(false);
+test(true);
+test(false);
diff --git a/test/script/basic/JDK-8034055.js.EXPECTED b/test/script/basic/JDK-8034055.js.EXPECTED
new file mode 100644
index 00000000..c947f4ae
--- /dev/null
+++ b/test/script/basic/JDK-8034055.js.EXPECTED
@@ -0,0 +1,16 @@
+1
+2
+false
+true
+1
+ReferenceError: "y" is not defined
+false
+true
+1
+2
+false
+true
+1
+ReferenceError: "y" is not defined
+false
+true
diff --git a/test/script/basic/JDK-8037562.js b/test/script/basic/JDK-8037562.js
new file mode 100644
index 00000000..7534a0da
--- /dev/null
+++ b/test/script/basic/JDK-8037562.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * JDK-8037562: Nashorn: JSON.parse comes up with nonexistent entries if there are gaps between the keys
+ *
+ * @test
+ * @run
+ */
+
+var strs = [
+ '{ "0":0, "2":2 }',
+ '{ "0":"", "2":"" }',
+ '{ "0":0, "5":"hello" }',
+ '{ "0":"", "15":3234 }',
+]
+
+for (var i in strs) {
+ print(JSON.stringify(JSON.parse(strs[i])));
+}
diff --git a/test/script/basic/JDK-8037562.js.EXPECTED b/test/script/basic/JDK-8037562.js.EXPECTED
new file mode 100644
index 00000000..ea671713
--- /dev/null
+++ b/test/script/basic/JDK-8037562.js.EXPECTED
@@ -0,0 +1,4 @@
+{"0":0,"2":2}
+{"0":"","2":""}
+{"0":0,"5":"hello"}
+{"0":"","15":3234}
diff --git a/test/script/basic/JDK-8039387.js b/test/script/basic/JDK-8039387.js
new file mode 100644
index 00000000..8f903c1a
--- /dev/null
+++ b/test/script/basic/JDK-8039387.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8039387: Nashorn supports indexed access of List elements, but length property is not supported
+ *
+ * @test
+ * @run
+ */
+
+var ArrayList = Java.type("java.util.ArrayList")
+var list = new ArrayList(3)
+list.add("nashorn")
+list.add("js")
+list.add("ecmascript")
+var len = list.length
+print("length = " + len)
+for (var i = 0; i < len; i++)
+ print(list[i])
diff --git a/test/script/basic/JDK-8039387.js.EXPECTED b/test/script/basic/JDK-8039387.js.EXPECTED
new file mode 100644
index 00000000..5b9ce56d
--- /dev/null
+++ b/test/script/basic/JDK-8039387.js.EXPECTED
@@ -0,0 +1,4 @@
+length = 3
+nashorn
+js
+ecmascript
diff --git a/test/script/basic/JDK-8041998.js b/test/script/basic/JDK-8041998.js
new file mode 100644
index 00000000..33e4d136
--- /dev/null
+++ b/test/script/basic/JDK-8041998.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8041998: RegExp implementation is not thread-safe
+ *
+ * @test
+ * @run
+ */
+
+var Thread = java.lang.Thread;
+
+function run() {
+ var line = 'content-type: text/html';
+ for (var i = 0; i < 300; i++) {
+ Thread.sleep(1);
+ line.split(/: /);
+ }
+ print("done");
+}
+
+var threads = [];
+
+for (var i = 0; i < 4; i++) {
+ var thread = new Thread(run);
+ thread.start();
+ threads.push(thread);
+}
+
+for (var i = 0; i < 4; i++) {
+ threads[i].join();
+}
diff --git a/test/script/basic/JDK-8041998.js.EXPECTED b/test/script/basic/JDK-8041998.js.EXPECTED
new file mode 100644
index 00000000..8f92fbfa
--- /dev/null
+++ b/test/script/basic/JDK-8041998.js.EXPECTED
@@ -0,0 +1,4 @@
+done
+done
+done
+done
diff --git a/test/script/basic/JDK-8042364.js b/test/script/basic/JDK-8042364.js
new file mode 100644
index 00000000..d8b81e24
--- /dev/null
+++ b/test/script/basic/JDK-8042364.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8042364: Make __proto__ ES6 draft compliant
+ *
+ * @test
+ * @run
+ */
+
+// check for Object.prototype.__proto__ accessor property
+print("Object.prototype has __proto__?",
+ Object.prototype.hasOwnProperty("__proto__"))
+
+var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__")
+print("descriptor");
+print(JSON.stringify(desc))
+print("getter", desc.get)
+print("setter", desc.set)
+
+// no computed "__proto__" name, only identifier!
+var p = {}
+var obj = {
+ "__proto__" : p
+}
+
+if (Object.getPrototypeOf(obj) === p) {
+ fail("obj has wrong __proto__, allows computed __proto__!")
+}
+
+if (obj.__proto__ !== p) {
+ fail("__proto__ not created as normal property!")
+}
+
+if (Object.getPrototypeOf(obj) !== Object.prototype) {
+ fail("obj has wrong __proto__")
+}
+
+var obj2 = {
+ __proto__: p
+}
+
+if (Object.getPrototypeOf(obj2) !== p) {
+ fail("can't set __proto__ in object literal")
+}
diff --git a/test/script/basic/JDK-8042364.js.EXPECTED b/test/script/basic/JDK-8042364.js.EXPECTED
new file mode 100644
index 00000000..b92947a8
--- /dev/null
+++ b/test/script/basic/JDK-8042364.js.EXPECTED
@@ -0,0 +1,5 @@
+Object.prototype has __proto__? true
+descriptor
+{"configurable":true,"enumerable":false}
+getter function getProto() { [native code] }
+setter function setProto() { [native code] }
diff --git a/test/script/basic/NASHORN-111.js.EXPECTED b/test/script/basic/NASHORN-111.js.EXPECTED
index 287f2558..0967ef42 100644
--- a/test/script/basic/NASHORN-111.js.EXPECTED
+++ b/test/script/basic/NASHORN-111.js.EXPECTED
@@ -1 +1 @@
-{"message":"type error"}
+{}
diff --git a/test/script/basic/NASHORN-173.js.EXPECTED b/test/script/basic/NASHORN-173.js.EXPECTED
index a0781a88..5375ecb1 100644
--- a/test/script/basic/NASHORN-173.js.EXPECTED
+++ b/test/script/basic/NASHORN-173.js.EXPECTED
@@ -132,7 +132,7 @@ RangeError
2.3423446609034533e+21
2.3423446609034533e+21
11111101111101010001111111010101101000101011011001001000000000000000000
-2224143002343343220233144213324
+2224143002343343220233044213324
375752177255053311000000
73b92b9962990aa44400
7efa8fead15b240000
diff --git a/test/script/basic/NASHORN-441.js.EXPECTED b/test/script/basic/NASHORN-441.js.EXPECTED
index de9ea224..c0038426 100644
--- a/test/script/basic/NASHORN-441.js.EXPECTED
+++ b/test/script/basic/NASHORN-441.js.EXPECTED
@@ -12,6 +12,6 @@ finally 4
try 5
rethrow 5
finally 5
-Error: try 5 thrown in line 71
+Error: try 5 thrown in line 74
try 6
finally 6
diff --git a/test/script/basic/dataview_endian.js b/test/script/basic/dataview_endian.js
new file mode 100644
index 00000000..f7607c0e
--- /dev/null
+++ b/test/script/basic/dataview_endian.js
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// set/get endianess checks
+
+var buffer = new ArrayBuffer(4);
+var dv = new DataView(buffer);
+
+// write (default) big endian, read big/little endian
+dv.setUint16(0, 0xABCD);
+Assert.assertEquals(dv.getUint16(0), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, false), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, true), 0xCDAB);
+
+// write little endian, read big/little endian
+dv.setUint16(0, 0xABCD, true);
+Assert.assertEquals(dv.getUint16(0), 0xCDAB);
+Assert.assertEquals(dv.getUint16(0, false), 0xCDAB);
+Assert.assertEquals(dv.getUint16(0, true), 0xABCD);
+
+// write explicit big endian, read big/little endian
+dv.setUint16(0, 0xABCD, false);
+Assert.assertEquals(dv.getUint16(0), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, false), 0xABCD);
+Assert.assertEquals(dv.getUint16(0, true), 0xCDAB);
+
+// write (default) big endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, false), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, true), 0x89EFCDAB);
+
+// write little endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89, true);
+Assert.assertEquals(dv.getUint32(0), 0x89EFCDAB);
+Assert.assertEquals(dv.getUint32(0, false), 0x89EFCDAB);
+Assert.assertEquals(dv.getUint32(0, true), 0xABCDEF89);
+
+// write explicit big endian, read big/little endian
+dv.setUint32(0, 0xABCDEF89, false);
+Assert.assertEquals(dv.getUint32(0), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, false), 0xABCDEF89);
+Assert.assertEquals(dv.getUint32(0, true), 0x89EFCDAB);
diff --git a/test/script/basic/dataview_getset.js b/test/script/basic/dataview_getset.js
new file mode 100644
index 00000000..8c7a994c
--- /dev/null
+++ b/test/script/basic/dataview_getset.js
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// checking get/set of values of various types
+// Also basic endianess check.
+
+var Float = Java.type("java.lang.Float");
+var Double = Java.type("java.lang.Double");
+
+var DOUBLE_MIN = Double.MIN_VALUE;
+var DOUBLE_MIN_NORMAL = Double.MIN_NORMAL;
+var FLOAT_MIN = Float.MIN_VALUE;
+var FLOAT_MIN_NORMAL = Float.MIN_NORMAL;
+
+var buffer = new ArrayBuffer(12);
+var dv = new DataView(buffer);
+
+dv.setInt8(1, 123);
+Assert.assertEquals(dv.getInt8(1), 123);
+dv.setInt8(1, 123, true);
+Assert.assertEquals(dv.getInt8(1, true), 123);
+
+dv.setUint8(1, 255);
+Assert.assertEquals(dv.getUint8(1), 255);
+dv.setUint8(1, 255, true);
+Assert.assertEquals(dv.getUint8(1, true), 255);
+
+dv.setInt16(1, 1234);
+Assert.assertEquals(dv.getInt16(1), 1234);
+dv.setInt16(1, 1234, true);
+Assert.assertEquals(dv.getInt16(1, true), 1234);
+
+dv.setUint16(1, 65535);
+Assert.assertEquals(dv.getUint16(1), 65535);
+dv.setUint16(1, 65535, true);
+Assert.assertEquals(dv.getUint16(1, true), 65535);
+
+dv.setInt32(1, 1234);
+Assert.assertEquals(dv.getInt32(1), 1234);
+dv.setInt32(1, 1234, true);
+Assert.assertEquals(dv.getInt32(1, true), 1234);
+
+dv.setUint32(1, 4294967295);
+Assert.assertEquals(dv.getUint32(1), 4294967295);
+dv.setUint32(1, 4294967295, true);
+Assert.assertEquals(dv.getUint32(1, true), 4294967295);
+
+dv.setFloat64(1, Math.PI);
+Assert.assertEquals(dv.getFloat64(1), Math.PI, DOUBLE_MIN);
+dv.setFloat64(1, Math.PI, true);
+Assert.assertEquals(dv.getFloat64(1, true), Math.PI, DOUBLE_MIN);
+
+dv.setFloat64(1, DOUBLE_MIN_NORMAL);
+Assert.assertEquals(dv.getFloat64(1), DOUBLE_MIN_NORMAL, DOUBLE_MIN);
+dv.setFloat64(1, DOUBLE_MIN_NORMAL, true);
+Assert.assertEquals(dv.getFloat64(1, true), DOUBLE_MIN_NORMAL, DOUBLE_MIN);
+
+dv.setFloat32(1, 1.414);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1), 1.414, FLOAT_MIN);
+dv.setFloat32(1, 1.414, true);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1, true), 1.414, FLOAT_MIN);
+
+dv.setFloat32(1, FLOAT_MIN_NORMAL);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1), FLOAT_MIN_NORMAL, FLOAT_MIN);
+dv.setFloat32(1, FLOAT_MIN_NORMAL, true);
+Assert["assertEquals(float, float, float)"](dv.getFloat32(1, true), FLOAT_MIN_NORMAL, FLOAT_MIN);
diff --git a/test/script/basic/dataview_new.js b/test/script/basic/dataview_new.js
new file mode 100644
index 00000000..78f8183d
--- /dev/null
+++ b/test/script/basic/dataview_new.js
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8015958: DataView constructor is not defined
+ *
+ * @test
+ * @run
+ */
+
+// basic DataView constructor checks.
+
+// check ArrayBufferView property values of DataView instance
+function check(dv, buf, offset, length) {
+ if (dv.buffer !== buf) {
+ fail("DataView.buffer is wrong");
+ }
+
+ if (dv.byteOffset != offset) {
+ fail("DataView.byteOffset = " + dv.byteOffset + ", expected " + offset);
+ }
+
+ if (dv.byteLength != length) {
+ fail("DataView.byteLength = " + dv.byteLength + ", expected " + length);
+ }
+}
+
+var buffer = new ArrayBuffer(12);
+check(new DataView(buffer), buffer, 0, 12);
+check(new DataView(buffer, 2), buffer, 2, 10);
+check(new DataView(buffer, 4, 8), buffer, 4, 8);
+
+// make sure expected error is thrown
+function checkError(callback, ErrorType) {
+ try {
+ callback();
+ fail("Should have thrown " + ErrorType.name);
+ } catch (e) {
+ if (! (e instanceof ErrorType)) {
+ fail("Expected " + ErrorType.name + " got " + e);
+ }
+ }
+}
+
+// non ArrayBuffer as first arg
+checkError(function() { new DataView(344) }, TypeError);
+
+// illegal offset/length values
+checkError(function() { new DataView(buffer, -1) }, RangeError);
+checkError(function() { new DataView(buffer, 15) }, RangeError);
+checkError(function() { new DataView(buffer, 1, 32) }, RangeError);
diff --git a/test/script/basic/list.js b/test/script/basic/list.js
index 72ae0be7..59136c0b 100644
--- a/test/script/basic/list.js
+++ b/test/script/basic/list.js
@@ -33,7 +33,7 @@ print("l.class.name=" + Java.typeName(l.class)) // Has "class" property like any
l.add("foo")
l.add("bar")
-print("l.length=" + l.length) // doesn't work, returns undefined
+print("l.length=" + l.length) // works, maps to l.size()
print("l.size()=" + l.size()) // this will work
print("l[0]=" + l[0])
diff --git a/test/script/basic/list.js.EXPECTED b/test/script/basic/list.js.EXPECTED
index 18feade2..47f3bd4f 100644
--- a/test/script/basic/list.js.EXPECTED
+++ b/test/script/basic/list.js.EXPECTED
@@ -1,5 +1,5 @@
l.class.name=java.util.ArrayList
-l.length=undefined
+l.length=2
l.size()=2
l[0]=foo
l[1]=bar
diff --git a/test/script/currently-failing/gettersetter.js b/test/script/currently-failing/gettersetter.js
new file mode 100644
index 00000000..88f69492
--- /dev/null
+++ b/test/script/currently-failing/gettersetter.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ return {
+ get foo() { return 42; },
+ set foo(x) {}
+ }
+}
+
+var obj1 = Foo();
+var obj2 = Foo();
+
+assertSameMap(obj1, obj2, "Object literals before change");
+
+Object.defineProperty(obj2, "foo", { get: function() { return 'hello' } });
+assertSameMap(obj1, obj2);
+
+Object.defineProperty(obj2, "foo", { set: function(x) { print(x) } });
+assertSameMap(obj1, obj2);
diff --git a/test/script/error/JDK-8027933.js b/test/script/error/JDK-8027933.js
new file mode 100644
index 00000000..9b398fa5
--- /dev/null
+++ b/test/script/error/JDK-8027933.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8027933: Add const.as.var option
+ *
+ * @test/compile-error
+ */
+
+// without --const-as-var the following should fail to compile
+const THE_ANSWER = 42;
diff --git a/test/script/error/JDK-8027933.js.EXPECTED b/test/script/error/JDK-8027933.js.EXPECTED
new file mode 100644
index 00000000..9389a5fc
--- /dev/null
+++ b/test/script/error/JDK-8027933.js.EXPECTED
@@ -0,0 +1,3 @@
+test/script/error/JDK-8027933.js:31:0 Expected an operand but found const
+const THE_ANSWER = 42;
+^
diff --git a/test/script/error/JDK-8039047.js b/test/script/error/JDK-8039047.js
new file mode 100644
index 00000000..8cbd51fd
--- /dev/null
+++ b/test/script/error/JDK-8039047.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8039047: Parser accepts conditional catch clauses even when --no-syntax-extensions / -nse option is passed
+ *
+ * @option --no-syntax-extensions
+ * @test/compile-error
+ */
+
+try {
+ func()
+} catch (e if e instanceof ReferenceError) {
+ print("Got ReferenceError " + e);
+}
diff --git a/test/script/error/JDK-8039047.js.EXPECTED b/test/script/error/JDK-8039047.js.EXPECTED
new file mode 100644
index 00000000..b1d2f170
--- /dev/null
+++ b/test/script/error/JDK-8039047.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/error/JDK-8039047.js:33:11 Expected ) but found if
+} catch (e if e instanceof ReferenceError) {
+ ^
+test/script/error/JDK-8039047.js:35:0 Expected eof but found }
+}
+^
diff --git a/test/script/maptests/builtins.js b/test/script/maptests/builtins.js
new file mode 100644
index 00000000..4de2ec9a
--- /dev/null
+++ b/test/script/maptests/builtins.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// check that builtin objects share property map
+
+assertSameMap(new Boolean(true), new Boolean(false));
+assertSameMap(new Number(3), new Number(Math.PI));
+assertSameMap(new String('hello'), new String('world'));
+assertSameMap(new Object(), new Object());
+assertSameMap(/hello/, /world/);
+// try w/without regexp flags
+assertSameMap(/hello/i, /world/g);
+assertSameMap(new Date(), new Date());
+assertSameMap(new Date(2000, 1, 1), new Date(1972, 5, 6));
+assertSameMap(Function(), Function());
+assertSameMap(Function("x", "return x"), Function("x", "return x*x"));
+assertSameMap(new Error(), new Error());
+assertSameMap(new Error('foo'), new Error('bar'));
+assertSameMap(new EvalError(), new EvalError());
+assertSameMap(new EvalError('foo'), new EvalError('bar'));
+assertSameMap(new RangeError(), new RangeError());
+assertSameMap(new RangeError('foo'), new RangeError('bar'));
+assertSameMap(new ReferenceError(), new ReferenceError());
+assertSameMap(new ReferenceError('foo'), new ReferenceError('bar'));
+assertSameMap(new SyntaxError(), new SyntaxError());
+assertSameMap(new SyntaxError('foo'), new SyntaxError('bar'));
+assertSameMap(new TypeError(), new TypeError());
+assertSameMap(new TypeError('foo'), new TypeError('bar'));
+assertSameMap(new URIError(), new URIError());
+assertSameMap(new URIError('foo'), new URIError('bar'));
diff --git a/test/script/maptests/constructor.js b/test/script/maptests/constructor.js
new file mode 100644
index 00000000..5722a3c1
--- /dev/null
+++ b/test/script/maptests/constructor.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "point.js");
+
+// use constructor defined in a different script file
+// These objects should share the map
+assertSameMap(new Point(2, 3), new Point(43, 23));
+assertSameMap(new Point(), new Point());
+assertSameMap(new Point(), new Point(3, 1));
diff --git a/test/script/maptests/maputil.js b/test/script/maptests/maputil.js
new file mode 100644
index 00000000..aa85d7f1
--- /dev/null
+++ b/test/script/maptests/maputil.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @subtest
+ */
+
+function assertSameMap(obj1, obj2, msg) {
+ if (! Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
+ fail(obj1.constructor + " instances don't share map");
+ }
+}
+
+function assertNotSameMap(obj1, obj2, msg) {
+ if (Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
+ fail(obj1.constructor + " and " + obj2.constructor + " instances share map");
+ }
+}
diff --git a/test/script/maptests/object_create.js b/test/script/maptests/object_create.js
new file mode 100644
index 00000000..1b1bd604
--- /dev/null
+++ b/test/script/maptests/object_create.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// Objects created by Object.create
+var obj1 = Object.create(Object.prototype);
+var obj2 = Object.create(Object.prototype);
+assertSameMap(obj1, obj2);
+
+var proto = { foo: 233 };
+obj1 = Object.create(proto);
+obj2 = Object.create(proto);
+assertSameMap(obj1, obj2);
diff --git a/test/script/maptests/object_literals.js b/test/script/maptests/object_literals.js
new file mode 100644
index 00000000..c73d8014
--- /dev/null
+++ b/test/script/maptests/object_literals.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// Object literals created at the same callsite
+function makeObject() {
+ return { foo: 34 }
+}
+assertSameMap(makeObject(), makeObject());
+
+function makeObject2() {
+ return { foo: 42, bar: 'hello' }
+}
+assertSameMap(makeObject2(), makeObject2());
+
+// Object literals created at different callsites
+assertSameMap({}, {});
+assertSameMap({foo: 4}, {foo: 'hello'});
+assertSameMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
diff --git a/test/script/maptests/point.js b/test/script/maptests/point.js
new file mode 100644
index 00000000..38b8fa25
--- /dev/null
+++ b/test/script/maptests/point.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * @subtest
+ */
+
+function Point(x, y) {
+ this.x =x; this.y =y;
+}
+
+Point.prototype.toString = function() {
+ return "(" + this.x + "," + this.y + ")";
+}
+
+Point.prototype.modulus = function() {
+ return Math.sqrt(this.x*this.x + this.y*this.y);
+}
+
+Point.prototype.argument = function() {
+ return Math.atan2(this.y, this.x);
+}
+
+load(__DIR__ + "maputil.js");
+
+assertSameMap(new Point(2, 3), new Point(43, 23));
+assertSameMap(new Point(), new Point());
+assertSameMap(new Point(), new Point(3, 1));
diff --git a/test/script/maptests/property_add.js b/test/script/maptests/property_add.js
new file mode 100644
index 00000000..20264554
--- /dev/null
+++ b/test/script/maptests/property_add.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {}
+
+var obj1 = new Foo();
+var obj2 = new Foo();
+
+assertSameMap(obj1, obj2);
+
+// property addition at same callsite
+function addX(obj, val) {
+ obj.x = val;
+}
+addX(obj1, 3);
+addX(obj2, 'hello');
+
+assertSameMap(obj1, obj2);
diff --git a/test/script/maptests/property_delete.js b/test/script/maptests/property_delete.js
new file mode 100644
index 00000000..e2824dd6
--- /dev/null
+++ b/test/script/maptests/property_delete.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+function Foo() {
+ this.x = 33;
+}
+
+var obj1 = new Foo();
+var obj2 = new Foo();
+
+assertSameMap(obj1, obj2);
+
+// property deletion at same callsite
+function deleteX(obj) {
+ delete obj.x;
+}
+deleteX(obj1);
+deleteX(obj2);
+
+assertSameMap(obj1, obj2);
diff --git a/test/script/maptests/proto.js b/test/script/maptests/proto.js
new file mode 100644
index 00000000..afb59509
--- /dev/null
+++ b/test/script/maptests/proto.js
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+load(__DIR__ + "maputil.js");
+
+// add/delete property to proto (direct/indirect) should
+// not affect the property map of the objects
+
+var proto2 = { foo: 334 }
+var proto = Object.create(proto2);
+proto.bar = "hello";
+
+var obj1 = Object.create(proto);
+var obj2 = Object.create(proto);
+
+assertSameMap(obj1, obj2);
+
+proto.newX = 'world';
+assertSameMap(obj1, obj2);
+
+delete proto.newX;
+assertSameMap(obj1, obj2);
+
+proto2.newX = "foo";
+assertSameMap(obj1, obj2);
+
+delete proto2.newX;
+assertSameMap(obj1, obj2);
+
+
diff --git a/test/script/sandbox/JDK-8031106.js b/test/script/sandbox/JDK-8031106.js
new file mode 100644
index 00000000..d5d83f69
--- /dev/null
+++ b/test/script/sandbox/JDK-8031106.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8031106: Nashorn: IndexOutOfBoundsException in NashornCallSiteDescriptor.getNameToken()
+ *
+ * @test
+ * @run
+ */
+
+var cl = new java.lang.Object().getClass();
+try {
+ cl["forName"];
+ fail("Should have thrown exception!");
+} catch (e) {
+ if (! (e instanceof java.lang.SecurityException)) {
+ fail("SecurityException expected, got " + e);
+ }
+}
diff --git a/test/script/sandbox/safeprops.js b/test/script/sandbox/safeprops.js
new file mode 100644
index 00000000..dc12e74f
--- /dev/null
+++ b/test/script/sandbox/safeprops.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Try to access System properties safe to read for any code.
+ * No security exception expected.
+ *
+ * @test
+ * @security
+ * @run
+ * @bug 8033924: Default permissions are not given for eval code
+ */
+
+var propNames = [
+ "java.version",
+ "java.vendor",
+ "java.vendor.url",
+ "java.class.version",
+ "os.name",
+ "os.version",
+ "os.arch",
+ "file.separator",
+ "path.separator",
+ "line.separator",
+ "java.specification.version",
+ "java.specification.vendor",
+ "java.specification.name",
+ "java.vm.specification.version",
+ "java.vm.specification.vendor",
+ "java.vm.specification.name",
+ "java.vm.version",
+ "java.vm.vendor",
+ "java.vm.name"
+];
+
+// no security exception expected
+for (var p in propNames) {
+ java.lang.System.getProperty(propNames[p]);
+}
+
+// no security exception expected
+for (var p in propNames) {
+ var name = propNames[p];
+ eval('java.lang.System.getProperty(name)');
+}
diff --git a/test/script/trusted/JDK-8006529.js b/test/script/trusted/JDK-8006529.js
index 8eb83909..3567c33e 100644
--- a/test/script/trusted/JDK-8006529.js
+++ b/test/script/trusted/JDK-8006529.js
@@ -113,7 +113,7 @@ function findFunction(node) {
var getContextMethod = Context.class.getMethod("getContext")
var getEnvMethod = Context.class.getMethod("getEnv")
-var SourceConstructor = Source.class.getConstructor(java.lang.String.class, java.lang.String.class)
+var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
@@ -121,7 +121,7 @@ var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
// source code, returns a jdk.nashorn.internal.ir.FunctionNode object
// representing it.
function compile(source) {
- var source = SourceConstructor.newInstance("<no name>", source);
+ var source = sourceForMethod.invoke(null, "<no name>", source);
var env = getEnvMethod.invoke(getContextMethod.invoke(null))
diff --git a/test/script/trusted/JDK-8032060.js b/test/script/trusted/JDK-8032060.js
new file mode 100644
index 00000000..8cb350cc
--- /dev/null
+++ b/test/script/trusted/JDK-8032060.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8032060: PropertyMap of Error objects is not stable
+ *
+ * @test
+ * @option -Dnashorn.debug=true
+ * @fork
+ * @run
+ */
+
+function checkMap(e1, e2) {
+ if (! Debug.identical(Debug.map(e1), Debug.map(e2))) {
+ fail("e1 and e2 have different maps");
+ }
+
+ var m1, m2;
+
+ try {
+ throw e1
+ } catch (e) {
+ m1 = Debug.map(e)
+ }
+
+ try {
+ throw e2
+ } catch (e) {
+ m2 = Debug.map(e)
+ }
+
+ if (! Debug.identical(m1, m2)) {
+ fail("e1 and e2 have different maps after being thrown");
+ }
+}
+
+checkMap(new Error(), new Error());
+checkMap(new EvalError(), new EvalError());
+checkMap(new RangeError(), new RangeError());
+checkMap(new ReferenceError(), new ReferenceError());
+checkMap(new SyntaxError(), new SyntaxError());
+checkMap(new TypeError(), new TypeError());
+checkMap(new URIError(), new URIError());
+
+// now try with message param
+checkMap(new Error("x"), new Error("y"));
+checkMap(new EvalError("x"), new EvalError("y"));
+checkMap(new RangeError("x"), new RangeError("y"));
+checkMap(new ReferenceError("x"), new ReferenceError("y"));
+checkMap(new SyntaxError("x"), new SyntaxError("y"));
+checkMap(new TypeError("x"), new TypeError("y"));
+checkMap(new URIError("x"), new URIError("y"));
diff --git a/test/src/jdk/nashorn/api/scripting/InvocableTest.java b/test/src/jdk/nashorn/api/scripting/InvocableTest.java
index fad3f372..a6722f57 100644
--- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java
+++ b/test/src/jdk/nashorn/api/scripting/InvocableTest.java
@@ -26,6 +26,7 @@
package jdk.nashorn.api.scripting;
import java.util.Objects;
+import java.util.function.Function;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
@@ -522,4 +523,16 @@ public class InvocableTest {
Assert.assertEquals(itf.test1(42, "a", "b"), "i == 42, strings instanceof java.lang.String[] == true, strings == [a, b]");
Assert.assertEquals(itf.test2(44, "c", "d", "e"), "arguments[0] == 44, arguments[1] instanceof java.lang.String[] == true, arguments[1] == [c, d, e]");
}
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void defaultMethodTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Invocable inv = (Invocable) e;
+
+ Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
+ Function<String, String> func = inv.getInterface(obj, Function.class);
+ assertEquals(func.apply("hello"), "HELLO");
+ }
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScopeTest.java b/test/src/jdk/nashorn/api/scripting/ScopeTest.java
index a18055bb..dc27d826 100644
--- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScopeTest.java
@@ -245,4 +245,320 @@ public class ScopeTest {
sb.put("x", "newX");
assertTrue(e.eval("x", ctx).equals("newX"));
}
+
+ /**
+ * Test multi-threaded access to defined global variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedVarTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "foo";
+
+ assertEquals(e.eval("var foo = 'original context';", origContext), null);
+ assertEquals(e.eval("var foo = 'new context';", newCtxt), null);
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval("var foo = 'newer context';", newCtxt), null);
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ assertEquals(e.eval(sharedScript), "original context");
+ assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded access to undefined global variables for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedGlobalTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ assertEquals(e.eval("foo = 'original context';", origContext), "original context");
+ assertEquals(e.eval("foo = 'new context';", newCtxt), "new context");
+ final String sharedScript = "foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ Assert.assertEquals(e.eval(sharedScript), "original context");
+ Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded access using the postfix ++ operator for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedIncTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ assertEquals(e.eval("var x = 0;", origContext), null);
+ assertEquals(e.eval("var x = 2;", newCtxt), null);
+ final String sharedScript = "x++;";
+
+ final Thread t1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < 1000; i++) {
+ assertEquals(e.eval(sharedScript, origContext), (double)i);
+ }
+ } catch (ScriptException se) {
+ fail(se.toString());
+ }
+ }
+ });
+ final Thread t2 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 2; i < 1000; i++) {
+ assertEquals(e.eval(sharedScript, newCtxt), (double)i);
+ }
+ } catch (ScriptException se) {
+ fail(se.toString());
+ }
+ }
+ });
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+ }
+
+ /**
+ * Test multi-threaded access to primitive prototype properties for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedPrimitiveTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
+ Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
+ assertEquals(obj1, "original context");
+ assertEquals(obj2, "new context");
+ final String sharedScript = "''.foo";
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "new context", 1000));
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+ assertEquals(obj3, "newer context");
+ final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
+ final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
+
+ t3.start();
+ t4.start();
+ t3.join();
+ t4.join();
+
+ Assert.assertEquals(e.eval(sharedScript), "original context");
+ Assert.assertEquals(e.eval(sharedScript, newCtxt), "newer context");
+ }
+
+ /**
+ * Test multi-threaded scope function invocation for shared script classes with multiple globals.
+ */
+ @Test
+ public static void multiThreadedFunctionTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), origContext);
+ assertEquals(origContext.getAttribute("scopeVar"), 1);
+ assertEquals(e.eval("scopeTest()"), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/func.js")), newCtxt);
+ assertEquals(newCtxt.getAttribute("scopeVar"), 1);
+ assertEquals(e.eval("scopeTest();", newCtxt), 1);
+
+ assertEquals(e.eval("scopeVar = 3;", newCtxt), 3);
+ assertEquals(newCtxt.getAttribute("scopeVar"), 3);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, "scopeTest()", 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, "scopeTest()", 3, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ }
+
+ /**
+ * Test multi-threaded access to global getters and setters for shared script classes with multiple globals.
+ */
+ @Test
+ public static void getterSetterTest() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "accessor1";
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext);
+ assertEquals(e.eval("accessor1 = 1;"), 1);
+ assertEquals(e.eval(sharedScript), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt);
+ assertEquals(e.eval("accessor1 = 2;", newCtxt), 2);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval(sharedScript), 1);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+ assertEquals(e.eval("v"), 1);
+ assertEquals(e.eval("v", newCtxt), 2);
+ }
+
+ /**
+ * Test multi-threaded access to global getters and setters for shared script classes with multiple globals.
+ */
+ @Test
+ public static void getterSetter2Test() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final Bindings b = e.createBindings();
+ final ScriptContext origContext = e.getContext();
+ final ScriptContext newCtxt = new SimpleScriptContext();
+ newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+ final String sharedScript = "accessor2";
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), origContext);
+ assertEquals(e.eval("accessor2 = 1;"), 1);
+ assertEquals(e.eval(sharedScript), 1);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/gettersetter.js")), newCtxt);
+ assertEquals(e.eval("accessor2 = 2;", newCtxt), 2);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+
+
+ final Thread t1 = new Thread(new ScriptRunner(e, origContext, sharedScript, 1, 1000));
+ final Thread t2 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, 2, 1000));
+
+ t1.start();
+ t2.start();
+ t1.join();
+ t2.join();
+
+ assertEquals(e.eval(sharedScript), 1);
+ assertEquals(e.eval(sharedScript, newCtxt), 2);
+ assertEquals(e.eval("x"), 1);
+ assertEquals(e.eval("x", newCtxt), 2);
+ }
+
+ /**
+ * Test "slow" scopes involving {@code with} and {@code eval} statements for shared script classes with multiple globals.
+ */
+ @Test
+ public static void testSlowScope() throws ScriptException, InterruptedException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ for (int i = 0; i < 100; i++) {
+ final Bindings b = e.createBindings();
+ final ScriptContext ctxt = new SimpleScriptContext();
+ ctxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
+
+ e.eval(new URLReader(ScopeTest.class.getResource("resources/witheval.js")), ctxt);
+ assertEquals(e.eval("a", ctxt), 1);
+ assertEquals(b.get("a"), 1);
+ assertEquals(e.eval("b", ctxt), 3);
+ assertEquals(b.get("b"), 3);
+ assertEquals(e.eval("c", ctxt), 10);
+ assertEquals(b.get("c"), 10);
+ }
+ }
+
+ private static class ScriptRunner implements Runnable {
+
+ final ScriptEngine engine;
+ final ScriptContext context;
+ final String source;
+ final Object expected;
+ final int iterations;
+
+ ScriptRunner(final ScriptEngine engine, final ScriptContext context, final String source, final Object expected, final int iterations) {
+ this.engine = engine;
+ this.context = context;
+ this.source = source;
+ this.expected = expected;
+ this.iterations = iterations;
+ }
+
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < iterations; i++) {
+ assertEquals(engine.eval(source, context), expected);
+ }
+ } catch (ScriptException se) {
+ throw new RuntimeException(se);
+ }
+ }
+ }
+
}
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index df8696d8..52199145 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -560,6 +560,47 @@ public class ScriptEngineTest {
assertTrue(reached[0]);
}
+ // properties that can be read by any code
+ private static String[] propNames = {
+ "java.version",
+ "java.vendor",
+ "java.vendor.url",
+ "java.class.version",
+ "os.name",
+ "os.version",
+ "os.arch",
+ "file.separator",
+ "path.separator",
+ "line.separator",
+ "java.specification.version",
+ "java.specification.vendor",
+ "java.specification.name",
+ "java.vm.specification.version",
+ "java.vm.specification.vendor",
+ "java.vm.specification.name",
+ "java.vm.version",
+ "java.vm.vendor",
+ "java.vm.name"
+ };
+
+ // @bug 8033924: Default permissions are not given for eval code
+ @Test
+ public void checkPropertyReadPermissions() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+
+ for (final String name : propNames) {
+ checkProperty(e, name);
+ }
+ }
+
+ private static void checkProperty(final ScriptEngine e, final String name)
+ throws ScriptException {
+ String value = System.getProperty(name);
+ e.put("name", name);
+ assertEquals(value, e.eval("java.lang.System.getProperty(name)"));
+ }
+
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
// Returns String that would be the result of calling PrintWriter.println
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
index 544f4ea7..241f22c3 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
+++ b/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
@@ -25,6 +25,7 @@
package jdk.nashorn.api.scripting;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -230,6 +231,29 @@ public class ScriptObjectMirrorTest {
}
@Test
+ public void indexPropertiesExternalBufferTest() throws ScriptException {
+ final ScriptEngineManager m = new ScriptEngineManager();
+ final ScriptEngine e = m.getEngineByName("nashorn");
+ final ScriptObjectMirror obj = (ScriptObjectMirror)e.eval("var obj = {}; obj");
+ final ByteBuffer buf = ByteBuffer.allocate(5);
+ int i;
+ for (i = 0; i < 5; i++) {
+ buf.put(i, (byte)(i+10));
+ }
+ obj.setIndexedPropertiesToExternalArrayData(buf);
+
+ for (i = 0; i < 5; i++) {
+ assertEquals((byte)(i+10), ((Number)e.eval("obj[" + i + "]")).byteValue());
+ }
+
+ e.eval("for (i = 0; i < 5; i++) obj[i] = 0");
+ for (i = 0; i < 5; i++) {
+ assertEquals((byte)0, ((Number)e.eval("obj[" + i + "]")).byteValue());
+ assertEquals((byte)0, buf.get(i));
+ }
+ }
+
+ @Test
public void conversionTest() throws ScriptException {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine e = m.getEngineByName("nashorn");
diff --git a/test/src/jdk/nashorn/api/scripting/resources/func.js b/test/src/jdk/nashorn/api/scripting/resources/func.js
new file mode 100644
index 00000000..477bd1a6
--- /dev/null
+++ b/test/src/jdk/nashorn/api/scripting/resources/func.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var scopeVar = 1;
+var global = this;
+undefGlobal = this;
+
+function scopeTest() {
+ if (this !== global) {
+ throw new Error("this !== global");
+ }
+ if (this !== undefGlobal) {
+ throw new Error("this !== undefinedGlobal")
+ }
+ return scopeVar;
+}
+
+scopeTest();
diff --git a/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js b/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js
new file mode 100644
index 00000000..51e24727
--- /dev/null
+++ b/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var v;
+
+Object.defineProperty(this, "accessor1", {
+ get: function() { return v; },
+ set: function(n) { v = n; }
+});
+
+Object.defineProperty(this, "accessor2", {
+ get: function() { return x; },
+ set: function(n) { x = n; }
+});
diff --git a/test/src/jdk/nashorn/api/scripting/resources/witheval.js b/test/src/jdk/nashorn/api/scripting/resources/witheval.js
new file mode 100644
index 00000000..6041d5b4
--- /dev/null
+++ b/test/src/jdk/nashorn/api/scripting/resources/witheval.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// This script is loaded from jdk.nashorn.api.scripting.ScopeTest to test script class sharing and reuse.
+
+var a;
+
+function outer(p, e) {
+ eval(e);
+ with(p) {
+ function inner() {
+ a = 1;
+ c = 10;
+ if (a !== 1) {
+ throw new Error("a !== 1");
+ }
+ if (b !== 3) {
+ throw new Error("b !== 3");
+ }
+ if (c !== 10) {
+ throw new Error("c !== 10");
+ }
+ }
+ inner();
+ }
+}
+
+outer({}, "b = 3;");
+
+if (a !== 1) {
+ throw new Error("a !== 1");
+}
+if (b !== 3) {
+ throw new Error("b !== 3");
+}
+if (c !== 10) {
+ throw new Error("c !== 10");
+}
diff --git a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
index 00d79acb..1ebb97a2 100644
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
+++ b/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
@@ -25,13 +25,16 @@
package jdk.nashorn.internal.codegen;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import static jdk.nashorn.internal.runtime.Source.readFully;
+
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;
import org.testng.Assert;
@@ -58,7 +61,7 @@ public class CompilerTest {
}
private Context context;
- private ScriptObject global;
+ private Global global;
@BeforeClass
public void setupTest() {
@@ -68,6 +71,7 @@ public class CompilerTest {
options.set("print.ast", true);
options.set("print.parse", true);
options.set("scripting", true);
+ options.set("const.as.var", true);
final ErrorManager errors = new ErrorManager() {
@Override
@@ -146,11 +150,11 @@ public class CompilerTest {
log("Begin compiling " + file.getAbsolutePath());
}
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
- final char[] buffer = Source.readFully(file);
+ final char[] buffer = readFully(file);
boolean excluded = false;
if (filter != null) {
@@ -169,7 +173,7 @@ public class CompilerTest {
if (globalChanged) {
Context.setGlobal(global);
}
- final Source source = new Source(file.getAbsolutePath(), buffer);
+ final Source source = sourceFor(file.getAbsolutePath(), buffer);
final ScriptFunction script = context.compileScript(source, global);
if (script == null || context.getErrorManager().getNumberOfErrors() > 0) {
log("Compile failed: " + file.getAbsolutePath());
diff --git a/test/src/jdk/nashorn/internal/parser/ParserTest.java b/test/src/jdk/nashorn/internal/parser/ParserTest.java
index 3e10a89e..8a68bb11 100644
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java
+++ b/test/src/jdk/nashorn/internal/parser/ParserTest.java
@@ -25,6 +25,9 @@
package jdk.nashorn.internal.parser;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import static jdk.nashorn.internal.runtime.Source.readFully;
+
import java.io.File;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
@@ -62,6 +65,7 @@ public class ParserTest {
options.set("anon.functions", true);
options.set("parse.only", true);
options.set("scripting", true);
+ options.set("const.as.var", true);
ErrorManager errors = new ErrorManager();
this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
@@ -131,7 +135,7 @@ public class ParserTest {
}
try {
- final char[] buffer = Source.readFully(file);
+ final char[] buffer = readFully(file);
boolean excluded = false;
if (filter != null) {
final String content = new String(buffer);
@@ -153,7 +157,7 @@ public class ParserTest {
}
};
errors.setLimit(0);
- final Source source = new Source(file.getAbsolutePath(), buffer);
+ final Source source = sourceFor(file.getAbsolutePath(), buffer);
new Parser(context.getEnv(), source, errors).parse();
if (errors.getNumberOfErrors() > 0) {
log("Parse failed: " + file.getAbsolutePath());
diff --git a/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java b/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
index 999f6fa4..ce969210 100644
--- a/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
+++ b/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
@@ -31,9 +31,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
/**
@@ -89,7 +89,7 @@ public class PerformanceWrapper extends jdk.nashorn.tools.Shell {
@Override
protected Object apply(final ScriptFunction target, final Object self) {
if (_runsPerIteration == 0 && _numberOfIterations == 0) {
- final ScriptObject global = jdk.nashorn.internal.runtime.Context.getGlobal();
+ final Global global = jdk.nashorn.internal.runtime.Context.getGlobal();
final ScriptFunction _target = target;
final Object _self = self;
diff --git a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
new file mode 100644
index 00000000..a2d72ebf
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Path;
+import java.nio.file.FileSystems;
+import javax.script.ScriptException;
+import org.testng.annotations.Test;
+import javax.script.ScriptEngine;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @test
+ * @bug 8039185 8039403
+ * @summary Test for persistent code cache and path handling
+ * @run testng jdk.nashorn.internal.runtime.CodeStoreAndPathTest
+ */
+
+public class CodeStoreAndPathTest {
+
+ final String code1 = "var code1; var x = 'Hello Script'; var x1 = 'Hello Script'; "
+ + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; "
+ + "var x4 = 'Hello Script'; var x5 = 'Hello Script';"
+ + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; "
+ + "var x8 = 'Hello Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';"
+ + "function f() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function g() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function h() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function i() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}";
+ final String code2 = "var code2; var x = 'Hello Script'; var x1 = 'Hello Script'; "
+ + "var x2 = 'Hello Script'; var x3 = 'Hello Script'; "
+ + "var x4 = 'Hello Script'; var x5 = 'Hello Script';"
+ + "var x6 = 'Hello Script'; var x7 = 'Hello Script'; "
+ + "var x8 = 'Hello Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';"
+ + "function f() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function g() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function h() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}"
+ + "function i() {x ='Bye Script'; x1 ='Bye Script'; x2='Bye Script';"
+ + "x3='Bye Script'; x4='Bye Script'; x5='Bye Script'; x6='Bye Script';"
+ + "x7='Bye Script'; x8='Bye Script'; var x9 = 'Hello Script'; "
+ + "var x10 = 'Hello Script';}";
+ // Script size < Default minimum size for storing a compiled script class
+ final String code3 = "var code3; var x = 'Hello Script'; var x1 = 'Hello Script'; ";
+ final String codeCache = "build/nashorn_code_cache";
+ final String oldUserDir = System.getProperty("user.dir");
+
+ public void checkCompiledScripts(DirectoryStream<Path> stream, int numberOfScripts) throws IOException {
+ for (Path file : stream) {
+ numberOfScripts--;
+ }
+ stream.close();
+ assertEquals(numberOfScripts,0);
+ }
+
+ @Test
+ public void pathHandlingTest() throws ScriptException, IOException {
+ System.setProperty("nashorn.persistent.code.cache", codeCache);
+ String[] options = new String[]{"--persistent-code-cache"};
+ NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ ScriptEngine e = fac.getScriptEngine(options);
+ Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache);
+ Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+ "nashorn.persistent.code.cache")).toAbsolutePath();
+ // Check that nashorn code cache is created in current working directory
+ assertEquals(actualCodeCachePath, expectedCodeCachePath);
+ // Check that code cache dir exists and it's not empty
+ File file = new File(actualCodeCachePath.toUri());
+ assertFalse(!file.isDirectory(), "No code cache directory was created!");
+ assertFalse(file.list().length == 0, "Code cache directory is empty!");
+ }
+
+ @Test
+ public void changeUserDirTest() throws ScriptException, IOException {
+ System.setProperty("nashorn.persistent.code.cache", codeCache);
+ String[] options = new String[]{"--persistent-code-cache"};
+ NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ ScriptEngine e = fac.getScriptEngine(options);
+ Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+ "nashorn.persistent.code.cache")).toAbsolutePath();
+ String newUserDir = "build/newUserDir";
+ // Now changing current working directory
+ System.setProperty("user.dir", System.getProperty("user.dir") + File.separator + newUserDir);
+ // Check that a new compiled script is stored in exisitng code cache
+ e.eval(code1);
+ DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+ // Already one compiled script has been stored in the cache during initialization
+ checkCompiledScripts(stream, 2);
+ // Setting to default current working dir
+ System.setProperty("user.dir", oldUserDir);
+ }
+
+ @Test
+ public void codeCacheTest() throws ScriptException, IOException {
+ System.setProperty("nashorn.persistent.code.cache", codeCache);
+ String[] options = new String[]{"--persistent-code-cache"};
+ NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+ ScriptEngine e = fac.getScriptEngine(options);
+ Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+ "nashorn.persistent.code.cache")).toAbsolutePath();
+ e.eval(code1);
+ e.eval(code2);
+ e.eval(code3);// less than minimum size for storing
+ // Already one compiled script has been stored in the cache during initialization
+ // adding code1 and code2.
+ DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+ checkCompiledScripts(stream, 3);
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/test/src/jdk/nashorn/internal/runtime/ContextTest.java
index 1b21c23f..4c4a8c65 100644
--- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java
@@ -25,10 +25,12 @@
package jdk.nashorn.internal.runtime;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Map;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.options.Options;
import org.testng.annotations.Test;
@@ -45,7 +47,7 @@ public class ContextTest {
final Options options = new Options("");
final ErrorManager errors = new ErrorManager();
final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
Context.setGlobal(cx.createGlobal());
try {
String code = "22 + 10";
@@ -65,7 +67,7 @@ public class ContextTest {
final ErrorManager errors = new ErrorManager();
final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
final boolean strict = cx.getEnv()._strict;
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
Context.setGlobal(cx.createGlobal());
try {
@@ -106,7 +108,7 @@ public class ContextTest {
}
private Object eval(final Context cx, final String name, final String code) {
- final Source source = new Source(name, code);
+ final Source source = sourceFor(name, code);
final ScriptObject global = Context.getGlobal();
final ScriptFunction func = cx.compileScript(source, global);
return func != null ? ScriptRuntime.apply(func, global) : null;
diff --git a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
new file mode 100644
index 00000000..7b84f5a7
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.internal.runtime;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import static org.testng.Assert.fail;
+import org.testng.annotations.Test;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+
+/**
+ * @test
+ * @bug 8037378
+ * @summary Sanity tests for no persistence caching
+ * @run testng/othervm jdk.nashorn.internal.runtime.NoPersistenceCachingTest
+ */
+public class NoPersistenceCachingTest {
+
+ private ScriptEngine engine;
+ private ScriptContext context1, context2, context3;
+ private ByteArrayOutputStream stderr;
+ private PrintStream prevStderr;
+
+ @BeforeTest
+ public void setupTest() {
+ stderr = new ByteArrayOutputStream();
+ prevStderr = System.err;
+ System.setErr(new PrintStream(stderr));
+ NashornScriptEngineFactory nashornFactory = null;
+ ScriptEngineManager sm = new ScriptEngineManager();
+ for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+ if (fac instanceof NashornScriptEngineFactory) {
+ nashornFactory = (NashornScriptEngineFactory) fac;
+ break;
+ }
+ }
+ if (nashornFactory == null) {
+ fail("Cannot find nashorn factory!");
+ }
+ String[] options = new String[]{"--log=compiler:finest"};
+ engine = nashornFactory.getScriptEngine(options);
+ context1 = engine.getContext();
+ context2 = new SimpleScriptContext();
+ context2.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+ context3 = new SimpleScriptContext();
+ context3.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+ }
+
+ @AfterTest
+ public void setErrTest() {
+ System.setErr(prevStderr);
+ }
+
+ public void runTest(int numberOfContext, String expectedOutputPattern,
+ int expectedPatternOccurrence) {
+
+ try {
+ switch (numberOfContext) {
+ case 2:
+ String scriptTwoContexts = "print('HelloTwoContexts')";
+ engine.eval(scriptTwoContexts, context1);
+ engine.eval(scriptTwoContexts, context2);
+ break;
+ case 3:
+ String scriptThreeContexts = "print('HelloThreeContexts')";
+ engine.eval(scriptThreeContexts, context1);
+ engine.eval(scriptThreeContexts, context2);
+ engine.eval(scriptThreeContexts, context3);
+ break;
+ }
+ } catch (final Exception se) {
+ se.printStackTrace();
+ fail(se.getMessage());
+ }
+ Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
+ Matcher matcher = deoptimizing.matcher(stderr.toString());
+ int matches = 0;
+ while (matcher.find()) {
+ matches++;
+ }
+ if (matches != expectedPatternOccurrence) {
+ fail("Number of cache hit is not correct, expected: "
+ + expectedPatternOccurrence + " and found: " + matches + "\n"
+ + stderr);
+ }
+ stderr.reset();
+ }
+
+ private static String getCodeCachePattern() {
+ return ("\\[compiler\\]\\sCode\\scache\\shit\\sfor\\s<eval>\\savoiding\\srecompile.");
+ }
+
+ @Test
+ public void twoContextTest() {
+ runTest(2, getCodeCachePattern(), 1);
+
+ }
+
+ @Test
+ public void threeContextTest() {
+ runTest(3, getCodeCachePattern(), 2);
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/test/src/jdk/nashorn/internal/runtime/SourceTest.java
new file mode 100644
index 00000000..34635856
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/SourceTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import jdk.nashorn.api.scripting.URLReader;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Arrays;
+
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * Tests different Source representations.
+ */
+public class SourceTest {
+
+ final private static String SOURCE_NAME = "source.js";
+ final private static String SOURCE_STRING = "var x = 1;";
+ final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray();
+ final private static String RESOURCE_PATH = "resources/load_test.js";
+ final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH);
+ final private static URL SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH);
+
+
+ @Test
+ public void testStringSource() {
+ testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_STRING));
+ testSources(sourceFor(SOURCE_NAME, SOURCE_STRING), sourceFor(SOURCE_NAME, SOURCE_CHARS));
+ }
+
+ @Test
+ public void testCharArraySource() {
+ testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_CHARS));
+ testSources(sourceFor(SOURCE_NAME, SOURCE_CHARS), sourceFor(SOURCE_NAME, SOURCE_STRING));
+ }
+
+ @Test
+ public void testURLSource() {
+ try {
+ testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, SOURCE_URL));
+ testSources(sourceFor(SOURCE_NAME, SOURCE_URL), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)));
+
+ } catch (final IOException e) {
+ fail(e.toString());
+ }
+ }
+
+ @Test
+ public void testURLReaderSource() {
+ try {
+ System.err.println(SourceTest.class.getResource(""));
+ testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)));
+ testSources(sourceFor(SOURCE_NAME, new URLReader(SOURCE_URL)), sourceFor(SOURCE_NAME, SOURCE_URL));
+ } catch (final IOException e) {
+ fail(e.toString());
+ }
+ }
+
+ @Test
+ public void testReaderSource() {
+ try {
+ testSources(sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)), sourceFor(SOURCE_NAME, getReader(RESOURCE_PATH)));
+ } catch (final IOException e) {
+ fail(e.toString());
+ }
+ }
+
+ @Test
+ public void testFileSource() {
+ try {
+ testSources(sourceFor(SOURCE_NAME, SOURCE_FILE), sourceFor(SOURCE_NAME, SOURCE_FILE));
+ } catch (final IOException e) {
+ fail(e.toString());
+ }
+ }
+
+ private Reader getReader(final String path) {
+ return new InputStreamReader(SourceTest.class.getResourceAsStream(path));
+ }
+
+ private void testSources(final Source source1, final Source source2) {
+ final char[] chars1 = source1.getContent();
+ final char[] chars2 = source2.getContent();
+ final String str1 = source1.getString();
+ final String str2 = source2.getString();
+ assertTrue(Arrays.equals(chars1, chars2));
+ assertEquals(str1, str2);
+ assertEquals(source1.hashCode(), source2.hashCode());
+ assertTrue(source1.equals(source2));
+ // Test for immutability
+ Arrays.fill(source1.getContent(), (char)0);
+ Arrays.fill(source2.getContent(), (char)1);
+ assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray()));
+ assertTrue(Arrays.equals(source1.getContent(), chars1));
+ assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));
+ }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
index 469d890e..f6da6f82 100644
--- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
@@ -220,4 +220,19 @@ public class TrustedScriptEngineTest {
// bar should be visible in default context
assertTrue(e.eval("typeof bar").equals("function"));
}
+
+
+ @Test public void nashornSwallowsConstKeyword() throws Exception {
+ final NashornScriptEngineFactory f = new NashornScriptEngineFactory();
+ final String[] args = new String[] { "--const-as-var" };
+ final ScriptEngine engine = f.getScriptEngine(args);
+
+ final Object ret = engine.eval(""
+ + "(function() {\n"
+ + " const x = 10;\n"
+ + " return x;\n"
+ + "})();"
+ );
+ assertEquals(ret, 10, "Parsed and executed OK");
+ }
}
diff --git a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
index ac2dc172..47ea7b32 100644
--- a/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
+++ b/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
@@ -25,6 +25,7 @@
package jdk.nashorn.internal.test.framework;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
import static jdk.nashorn.tools.Shell.COMPILATION_ERROR;
import static jdk.nashorn.tools.Shell.RUNTIME_ERROR;
import static jdk.nashorn.tools.Shell.SUCCESS;
@@ -34,12 +35,11 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import jdk.nashorn.api.scripting.NashornException;
+import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;
/**
@@ -110,12 +110,12 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
@Override
public int run(final OutputStream out, final OutputStream err, final String[] args) throws IOException {
- final ScriptObject oldGlobal = Context.getGlobal();
+ final Global oldGlobal = Context.getGlobal();
try {
ctxOut.setDelegatee(out);
ctxErr.setDelegatee(err);
final ErrorManager errors = context.getErrorManager();
- final ScriptObject global = context.createGlobal();
+ final Global global = context.createGlobal();
Context.setGlobal(global);
// For each file on the command line.
@@ -125,7 +125,7 @@ public final class SharedContextEvaluator implements ScriptEvaluator {
continue;
}
final File file = new File(fileName);
- ScriptFunction script = context.compileScript(new Source(fileName, file.toURI().toURL()), global);
+ ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
if (script == null || errors.getNumberOfErrors() != 0) {
return COMPILATION_ERROR;
diff --git a/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
new file mode 100644
index 00000000..947896b3
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.test.models;
+
+public class IntFloatOverloadSelection {
+
+ public static String overloadedMethod(int i) {
+ return "int";
+ }
+
+ public static String overloadedMethod(float f) {
+ return "float";
+ }
+}
diff --git a/test/src/jdk/nashorn/test/models/SourceHelper.java b/test/src/jdk/nashorn/test/models/SourceHelper.java
index 46b1e488..7e90f304 100644
--- a/test/src/jdk/nashorn/test/models/SourceHelper.java
+++ b/test/src/jdk/nashorn/test/models/SourceHelper.java
@@ -46,7 +46,7 @@ public final class SourceHelper {
}
public static String readFully(final URL url) throws IOException {
- return new Source(url.toString(), url).getString();
+ return Source.sourceFor(url.toString(), url).getString();
}
public static String readFully(final Reader reader) throws IOException {