diff --git a/enterprise/web.core/build.xml b/enterprise/web.core/build.xml
index d5b57b5dba68..94cd0e99c384 100644
--- a/enterprise/web.core/build.xml
+++ b/enterprise/web.core/build.xml
@@ -21,4 +21,7 @@
-->
org.graalvm.polyglot APIs.
- Use them to obtain directly, if you trust the provider of those APIs.
+ Use them to obtain access to the GraalVM directly, if you only
+ want to work with them and generic
+ Scripting
+ wrapper isn't enough.
GraalVM:something)
- run in a very restricted, secure sandbox. That means they cannot
+ run in a very restricted, secure sandbox. See
+ GraalSDK
+ for details. That means the languages cannot
access local files, ports, etc. Some languages (like
>FastR
implementation of the R language) need such access. In such
diff --git a/ide/libs.graalsdk/external/binaries-list b/ide/libs.graalsdk/external/binaries-list
index 516396da253f..70c4229b080a 100644
--- a/ide/libs.graalsdk/external/binaries-list
+++ b/ide/libs.graalsdk/external/binaries-list
@@ -14,4 +14,4 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-0E1CCE754C9EF8847B473FAB3F848D1FE324F09E org.graalvm.sdk:graal-sdk:1.0.0-rc12
+3C22A79D3CCCCFD161F4DD935C30C745F6FFF848 org.graalvm.sdk:graal-sdk:19.0.0
diff --git a/ide/libs.graalsdk/external/graal-sdk-1.0.0-license.txt b/ide/libs.graalsdk/external/graal-sdk-19.0.0-license.txt
similarity index 97%
rename from ide/libs.graalsdk/external/graal-sdk-1.0.0-license.txt
rename to ide/libs.graalsdk/external/graal-sdk-19.0.0-license.txt
index 7a5f1230e22f..927010dc26c6 100644
--- a/ide/libs.graalsdk/external/graal-sdk-1.0.0-license.txt
+++ b/ide/libs.graalsdk/external/graal-sdk-19.0.0-license.txt
@@ -2,8 +2,8 @@ Name: Graal SDK and Truffle API
Description: Graal SDK and Truffle API
License: UPL
Origin: https://github.com/oracle/graal
-Version: 1.0
-Files: graal-sdk-1.0.0-rc12.jar
+Version: 19.0.0
+Files: graal-sdk-19.0.0.jar
Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
diff --git a/ide/libs.graalsdk/nbproject/org-netbeans-libs-graalsdk.sig b/ide/libs.graalsdk/nbproject/org-netbeans-libs-graalsdk.sig
index 9a0f77cabebe..5557b9d42b01 100644
--- a/ide/libs.graalsdk/nbproject/org-netbeans-libs-graalsdk.sig
+++ b/ide/libs.graalsdk/nbproject/org-netbeans-libs-graalsdk.sig
@@ -1,5 +1,5 @@
#Signature file v4.1
-#Version 1.0.11
+#Version 1.1
CLSS public abstract interface java.io.Serializable
@@ -9,12 +9,6 @@ meth public abstract void close() throws java.lang.Exception
CLSS public abstract interface java.lang.Comparable<%0 extends java.lang.Object>
meth public abstract int compareTo({java.lang.Comparable%0})
-CLSS public abstract interface !annotation java.lang.Deprecated
- anno 0 java.lang.annotation.Documented()
- anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
- anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE])
-intf java.lang.annotation.Annotation
-
CLSS public abstract java.lang.Enum<%0 extends java.lang.Enum<{java.lang.Enum%0}>>
cons protected init(java.lang.String,int)
intf java.io.Serializable
@@ -125,9 +119,95 @@ CLSS public abstract interface !annotation java.lang.annotation.Target
intf java.lang.annotation.Annotation
meth public abstract java.lang.annotation.ElementType[] value()
+CLSS public abstract interface org.graalvm.collections.EconomicMap<%0 extends java.lang.Object, %1 extends java.lang.Object>
+intf org.graalvm.collections.UnmodifiableEconomicMap<{org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}>
+meth public abstract org.graalvm.collections.MapCursor<{org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}> getEntries()
+meth public abstract void clear()
+meth public abstract void replaceAll(java.util.function.BiFunction super {org.graalvm.collections.EconomicMap%0},? super {org.graalvm.collections.EconomicMap%1},? extends {org.graalvm.collections.EconomicMap%1}>)
+meth public abstract {org.graalvm.collections.EconomicMap%1} put({org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1})
+meth public abstract {org.graalvm.collections.EconomicMap%1} removeKey({org.graalvm.collections.EconomicMap%0})
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create()
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(int)
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.Equivalence)
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.Equivalence,int)
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.Equivalence,org.graalvm.collections.UnmodifiableEconomicMap<{%%0},{%%1}>)
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> create(org.graalvm.collections.UnmodifiableEconomicMap<{%%0},{%%1}>)
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.EconomicMap<{%%0},{%%1}> wrapMap(java.util.Map<{%%0},{%%1}>)
+meth public void putAll(org.graalvm.collections.EconomicMap<{org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}>)
+meth public void putAll(org.graalvm.collections.UnmodifiableEconomicMap extends {org.graalvm.collections.EconomicMap%0},? extends {org.graalvm.collections.EconomicMap%1}>)
+
+CLSS public abstract interface org.graalvm.collections.EconomicSet<%0 extends java.lang.Object>
+intf org.graalvm.collections.UnmodifiableEconomicSet<{org.graalvm.collections.EconomicSet%0}>
+meth public abstract boolean add({org.graalvm.collections.EconomicSet%0})
+meth public abstract void clear()
+meth public abstract void remove({org.graalvm.collections.EconomicSet%0})
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create()
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(int)
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence)
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,int)
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,org.graalvm.collections.UnmodifiableEconomicSet<{%%0}>)
+meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.UnmodifiableEconomicSet<{%%0}>)
+meth public void addAll(java.lang.Iterable<{org.graalvm.collections.EconomicSet%0}>)
+meth public void addAll(java.util.Iterator<{org.graalvm.collections.EconomicSet%0}>)
+meth public void addAll(org.graalvm.collections.EconomicSet<{org.graalvm.collections.EconomicSet%0}>)
+meth public void removeAll(java.lang.Iterable<{org.graalvm.collections.EconomicSet%0}>)
+meth public void removeAll(java.util.Iterator<{org.graalvm.collections.EconomicSet%0}>)
+meth public void removeAll(org.graalvm.collections.EconomicSet<{org.graalvm.collections.EconomicSet%0}>)
+meth public void retainAll(org.graalvm.collections.EconomicSet<{org.graalvm.collections.EconomicSet%0}>)
+
+CLSS public abstract org.graalvm.collections.Equivalence
+cons protected init()
+fld public final static org.graalvm.collections.Equivalence DEFAULT
+fld public final static org.graalvm.collections.Equivalence IDENTITY
+fld public final static org.graalvm.collections.Equivalence IDENTITY_WITH_SYSTEM_HASHCODE
+meth public abstract boolean equals(java.lang.Object,java.lang.Object)
+meth public abstract int hashCode(java.lang.Object)
+supr java.lang.Object
+
+CLSS public abstract interface org.graalvm.collections.MapCursor<%0 extends java.lang.Object, %1 extends java.lang.Object>
+intf org.graalvm.collections.UnmodifiableMapCursor<{org.graalvm.collections.MapCursor%0},{org.graalvm.collections.MapCursor%1}>
+meth public abstract void remove()
+
+CLSS public final org.graalvm.collections.Pair<%0 extends java.lang.Object, %1 extends java.lang.Object>
+meth public boolean equals(java.lang.Object)
+meth public int hashCode()
+meth public java.lang.String toString()
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.Pair<{%%0},{%%1}> create({%%0},{%%1})
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.Pair<{%%0},{%%1}> createLeft({%%0})
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.Pair<{%%0},{%%1}> createRight({%%1})
+meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.Pair<{%%0},{%%1}> empty()
+meth public {org.graalvm.collections.Pair%0} getLeft()
+meth public {org.graalvm.collections.Pair%1} getRight()
+supr java.lang.Object
+hfds EMPTY,left,right
+
+CLSS public abstract interface org.graalvm.collections.UnmodifiableEconomicMap<%0 extends java.lang.Object, %1 extends java.lang.Object>
+meth public abstract boolean containsKey({org.graalvm.collections.UnmodifiableEconomicMap%0})
+meth public abstract boolean isEmpty()
+meth public abstract int size()
+meth public abstract java.lang.Iterable<{org.graalvm.collections.UnmodifiableEconomicMap%0}> getKeys()
+meth public abstract java.lang.Iterable<{org.graalvm.collections.UnmodifiableEconomicMap%1}> getValues()
+meth public abstract org.graalvm.collections.UnmodifiableMapCursor<{org.graalvm.collections.UnmodifiableEconomicMap%0},{org.graalvm.collections.UnmodifiableEconomicMap%1}> getEntries()
+meth public abstract {org.graalvm.collections.UnmodifiableEconomicMap%1} get({org.graalvm.collections.UnmodifiableEconomicMap%0})
+meth public {org.graalvm.collections.UnmodifiableEconomicMap%1} get({org.graalvm.collections.UnmodifiableEconomicMap%0},{org.graalvm.collections.UnmodifiableEconomicMap%1})
+
+CLSS public abstract interface org.graalvm.collections.UnmodifiableEconomicSet<%0 extends java.lang.Object>
+intf java.lang.Iterable<{org.graalvm.collections.UnmodifiableEconomicSet%0}>
+meth public abstract boolean contains({org.graalvm.collections.UnmodifiableEconomicSet%0})
+meth public abstract boolean isEmpty()
+meth public abstract int size()
+meth public {org.graalvm.collections.UnmodifiableEconomicSet%0}[] toArray({org.graalvm.collections.UnmodifiableEconomicSet%0}[])
+
+CLSS public abstract interface org.graalvm.collections.UnmodifiableMapCursor<%0 extends java.lang.Object, %1 extends java.lang.Object>
+meth public abstract boolean advance()
+meth public abstract {org.graalvm.collections.UnmodifiableMapCursor%0} getKey()
+meth public abstract {org.graalvm.collections.UnmodifiableMapCursor%1} getValue()
+
CLSS public final !enum org.graalvm.options.OptionCategory
fld public final static org.graalvm.options.OptionCategory DEBUG
+ anno 0 java.lang.Deprecated()
fld public final static org.graalvm.options.OptionCategory EXPERT
+fld public final static org.graalvm.options.OptionCategory INTERNAL
fld public final static org.graalvm.options.OptionCategory USER
meth public static org.graalvm.options.OptionCategory valueOf(java.lang.String)
meth public static org.graalvm.options.OptionCategory[] values()
@@ -143,9 +223,10 @@ meth public java.lang.String getName()
meth public java.lang.String toString()
meth public org.graalvm.options.OptionCategory getCategory()
meth public org.graalvm.options.OptionKey> getKey()
+meth public org.graalvm.options.OptionStability getStability()
meth public static <%0 extends java.lang.Object> org.graalvm.options.OptionDescriptor$Builder newBuilder(org.graalvm.options.OptionKey<{%%0}>,java.lang.String)
supr java.lang.Object
-hfds EMPTY,deprecated,help,key,kind,name
+hfds EMPTY,deprecated,help,key,kind,name,stability
CLSS public final org.graalvm.options.OptionDescriptor$Builder
outer org.graalvm.options.OptionDescriptor
@@ -153,8 +234,9 @@ meth public org.graalvm.options.OptionDescriptor build()
meth public org.graalvm.options.OptionDescriptor$Builder category(org.graalvm.options.OptionCategory)
meth public org.graalvm.options.OptionDescriptor$Builder deprecated(boolean)
meth public org.graalvm.options.OptionDescriptor$Builder help(java.lang.String)
+meth public org.graalvm.options.OptionDescriptor$Builder stability(org.graalvm.options.OptionStability)
supr java.lang.Object
-hfds category,deprecated,help,key,name
+hfds category,deprecated,help,key,name,stability
CLSS public abstract interface org.graalvm.options.OptionDescriptors
fld public final static org.graalvm.options.OptionDescriptors EMPTY
@@ -174,9 +256,20 @@ meth public {org.graalvm.options.OptionKey%0} getValue(org.graalvm.options.Optio
supr java.lang.Object
hfds defaultValue,type
+CLSS public final !enum org.graalvm.options.OptionStability
+fld public final static org.graalvm.options.OptionStability EXPERIMENTAL
+fld public final static org.graalvm.options.OptionStability STABLE
+meth public static org.graalvm.options.OptionStability valueOf(java.lang.String)
+meth public static org.graalvm.options.OptionStability[] values()
+supr java.lang.Enum
- * As a secondary usecase, it is possible to request this module and gain access to
- * {@code org.graalvm.polyglot} package directly. Consult {@link Context} and {@link Engine}
+ * By default all the GraalVM engines
+ * (named GraalVM:something)
+ * run in a very restricted, secure sandbox:
+ *
+ * The languages cannot access local files, ports, etc. They can access public + * fields and public methods of objects passed into their scripts (but not + * those methods exposed by base {@link Object} class). The scripts can access + * elements of Java arrays and {@link List} elements. Methods of a + * {@linkplain FunctionalInterface functional interfaces} are callable by the + * scripts. + *
+ *
+ * For some languages such restrictions are too tight. They
+ * need to gain wider access. This can be done by setting allowAllAccess
+ * attribute to {@code true}:
+ *
+ * Once enabled, the {@link HostAccess#ALL} and {@link Builder#allowAllAccess(boolean) allowAllAccess(true)} + * is then used to construct the engine's environment. + *
+ *
+ * As a consequence of packaging the GraalVM APIs, it is possible to request this module and gain access to
+ * {@link org.graalvm.polyglot} package directly. Consult {@link Context} and {@link Engine}
* classes as a starting points when
- * accessing the Graal SDK polyglot API directly.
+ * accessing the Graal SDK directly. Preferably use only if the
+ * NetBeans Scripting
+ * API wrapper isn't good enough.
*/
public final class GraalSDK {
private GraalSDK() {
diff --git a/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalContext.java b/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalContext.java
index 296c1cbbed07..9ca97224832f 100644
--- a/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalContext.java
+++ b/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalContext.java
@@ -22,6 +22,9 @@
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -29,16 +32,38 @@
import javax.script.ScriptContext;
import javax.script.SimpleBindings;
import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.HostAccess;
+import org.graalvm.polyglot.PolyglotAccess;
import org.openide.util.io.ReaderInputStream;
final class GraalContext implements ScriptContext {
+ private final static String ALLOW_ALL_ACCESS = "allowAllAccess"; // NOI18N
private Context ctx;
private final WriterOutputStream writer = new WriterOutputStream(new OutputStreamWriter(System.out));
private final WriterOutputStream errorWriter = new WriterOutputStream(new OutputStreamWriter(System.err));
private Reader reader;
+ private final Bindings globals;
private SimpleBindings bindings;
private boolean allowAllAccess;
+ // BEGIN: org.netbeans.libs.graalsdk.impl.GraalContext#SANDBOX
+ private static final HostAccess SANDBOX = HostAccess.newBuilder().
+ allowPublicAccess(true).
+ allowArrayAccess(true).
+ allowListAccess(true).
+ allowAllImplementations(true).
+ denyAccess(Class.class).
+ denyAccess(Method.class).
+ denyAccess(Field.class).
+ denyAccess(Proxy.class).
+ denyAccess(Object.class, false).
+ build();
+ // END: org.netbeans.libs.graalsdk.impl.GraalContext#SANDBOX
+
+ GraalContext(Bindings globals) {
+ this.globals = globals;
+ }
+
synchronized final Context ctx() {
if (ctx == null) {
final Context.Builder b = Context.newBuilder();
@@ -51,15 +76,18 @@ synchronized final Context ctx() {
throw raise(RuntimeException.class, ex);
}
}
- if (allowAllAccess) {
+ b.allowPolyglotAccess(PolyglotAccess.ALL);
+ if (Boolean.TRUE.equals(getAttribute(ALLOW_ALL_ACCESS, ScriptContext.GLOBAL_SCOPE))) {
+ b.allowHostAccess(HostAccess.ALL);
b.allowAllAccess(true);
+ } else {
+ b.allowHostAccess(SANDBOX);
}
ctx = b.build();
}
return ctx;
}
-
@Override
public void setBindings(Bindings bindings, int scope) {
throw new UnsupportedOperationException();
@@ -85,7 +113,7 @@ private void assertGlobalScope(int scope) throws IllegalArgumentException {
@Override
public void setAttribute(String name, Object value, int scope) {
assertGlobalScope(scope);
- if ("allowAllAccess".equals(name)) { // NOI18N
+ if (ALLOW_ALL_ACCESS.equals(name)) {
if (this.ctx == null) {
this.allowAllAccess = Boolean.TRUE.equals(value);
return;
@@ -98,10 +126,12 @@ public void setAttribute(String name, Object value, int scope) {
@Override
public Object getAttribute(String name, int scope) {
assertGlobalScope(scope);
- if ("allowAllAccess".equals(name)) { // NOI18N
- return this.allowAllAccess;
+ if (ALLOW_ALL_ACCESS.equals(name)) {
+ if (this.allowAllAccess) {
+ return true;
+ }
}
- return null;
+ return globals == null ? null : globals.get(name);
}
@Override
diff --git a/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalEngineFactory.java b/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalEngineFactory.java
index 7f762b93cfdc..a60705a697a0 100644
--- a/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalEngineFactory.java
+++ b/ide/libs.graalsdk/src/org/netbeans/libs/graalsdk/impl/GraalEngineFactory.java
@@ -60,7 +60,7 @@ public List
- * Note: In Nashorn, JavaScript function arguments that are not used in the + * Note: In some engines, JavaScript function arguments that are not used in the * call will have a type of {@code Undefined}. * * @param objs diff --git a/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/ClassFilterPacHelpers.java b/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/ClassFilterPacHelpers.java deleted file mode 100644 index 7c5a742b2fce..000000000000 --- a/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/ClassFilterPacHelpers.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.netbeans.core.network.proxy.pac.impl; - -import jdk.nashorn.api.scripting.ClassFilter; -import org.netbeans.core.network.proxy.pac.PacHelperMethods; - -/** - * Nashorn class filter which helps us create a sandboxed JavaScript execution - * environment which only has access to the Helper methods, nothing more. - * - *
Note that the ClassFilter feature is specific to Nashorn (Rhino had the - * {@code ClassShutter} class for this purpose), but the feature did not appear - * until Java 8u40. - * - * @author lbruun - */ -class ClassFilterPacHelpers implements ClassFilter { - - @Override - public boolean exposeToScripts(String string) { - // The only Java class the PAC script is allowed to - // make use of is the PAC Helpers, nothing more. - return string.equals(PacHelperMethods.class.getName()); - } -} diff --git a/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/NbPacScriptEvaluator.java b/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/NbPacScriptEvaluator.java index 8b7f384d80b2..11c97b41c066 100644 --- a/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/NbPacScriptEvaluator.java +++ b/platform/core.network/src/org/netbeans/core/network/proxy/pac/impl/NbPacScriptEvaluator.java @@ -35,8 +35,7 @@ import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; import javax.script.ScriptException; -import jdk.nashorn.api.scripting.NashornScriptEngineFactory; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import org.netbeans.api.scripting.Scripting; import org.netbeans.core.network.utils.SimpleObjCache; import org.netbeans.core.network.proxy.pac.PacHelperMethods; import org.netbeans.core.network.proxy.pac.PacJsEntryFunction; @@ -46,16 +45,17 @@ import org.netbeans.core.network.proxy.pac.PacScriptEvaluator; import org.netbeans.core.network.proxy.pac.PacUtils; import org.openide.util.Lookup; +import org.openide.util.NbBundle; /** * NetBeans implementation of a PAC script evaluator. This implementation * is the one returned by {@link NbPacScriptEvaluatorFactory}. - * + * *
| Behavior | *Apache NetBeans |
@@ -148,31 +148,31 @@
* ??? | *
|---|