
package com.smartgwt.client.docs;

/**
 * <h3>Server Scripting</h3>
 * Smart GWT allows you to embed "scriptlets" directly in your .ds.xml and .app.xml files to take 
 * care of simple business logic without having to create a separate file or class to hold the
 * logic.
 *  <P>
 *  These scriptlets can be written in any language supported by the Java "JSR 223" standard,
 * including Java itself, as well as languages such as Groovy, JavaScript, Velocity, Python, Ruby,
 *  Scala and Clojure.
 *  <P>
 *  The primary use cases for server scripts are:<ul>
 * <li/>DMI scriptlet declared via {@link com.smartgwt.client.docs.serverds.DataSource#script
 * DataSource.script}. Like DMI logic declared via 
 * {@link com.smartgwt.client.docs.serverds.ServerObject}, DMI scriptlets can be used to add
 * business logic by modifying the DSRequest 
 *  before it is executed, modifying the default DSResponse, or taking other, unrelated actions.
 * <li/>DMI scriplet declared via {@link com.smartgwt.client.docs.serverds.OperationBinding#script
 * OperationBinding.script}, same as the above, but 
 * <code>operationBinding</code> specific and prioritized over the <code>DataSource.script</code> 
 *  if both present.
 * <li/>validator scriptlets declared via {@link
 * com.smartgwt.client.docs.serverds.Validator#serverCondition Validator.serverCondition}. Like a
 * validator declared via 
 * {@link com.smartgwt.client.docs.serverds.ServerObject}, a scriptlet validator defines whether
 * data is valid by running arbitrary logic, 
 *  then returning true or false.
 * <li/>scripted {@link com.smartgwt.client.docs.serverds.VisibleMethod} as part of {@link
 * com.smartgwt.client.docs.serverds.ServerObject#visibleMethods ServerObject.visibleMethods}
 * declared in
 *  an {@link com.smartgwt.client.docs.ApplicationDeclaration Application declaration file}.
 *  </ul>
 *  For example <code>DataSource.script</code> below is executed before all DataSource operations 
 * adding session ID to the request helping to ensure that users can only read or write to the
 * data 
 *  they own (you can see this in action 
 * <a href='https://www.smartclient.com/smartclient-latest/showcase/?id=scriptingUserSpecificData'
 * target='_blank'>here</a>): 
 *  <pre>
 *  &lt;DataSource ID="scripting_cartItem" ... &gt;
 *      &lt;script language="groovy"&gt;
 *          String sessionId = session.getId();
 *  
 *          if (DataSource.isAdd(dsRequest.getOperationType())) {
 *              dsRequest.setFieldValue("sessionId", sessionId);
 *          } else {
 *              dsRequest.setCriteriaValue("sessionId", sessionId);
 *          }
 *  
 *          return dsRequest.execute();
 *      &lt;/script&gt;
 *      ...
 *  &lt;/DataSource&gt;
 *  </pre>
 * Note that you can write Java code and execute it as Groovy script right away, so there's
 * basically no 
 * learning curve here. Java code works immediately and Groovy-specific shortcuts can be picked up
 * overtime.
 *  <P>
 * Another example below shows {@link com.smartgwt.client.docs.serverds.Validator#serverCondition
 * Validator.serverCondition} scriplet checking submitted value against 
 * value fetched from different DataSource ensuring it does not exceed it (you can see this in
 * action 
 * <a href='https://www.smartclient.com/smartclient-latest/showcase/?id=inlineScriptValidation2'
 * target='_blank'>here</a>): 
 *  <pre>
 *  &lt;field name="quantity" type="integer"&gt;
 *      &lt;validators&gt;
 *           &lt;validator type="serverCustom"&gt;
 *              &lt;serverCondition language="javascript"&gt;&lt;![CDATA[
 *                  value &lt; dataSources.get("StockItem").fetchById(record.get("itemId")).get("quantity")
 *              ]]>&lt;/serverCondition&gt;
 *              &lt;errorMessage&gt;Not enough in stock&lt;/errorMessage&gt;
 *          &lt;/validator&gt;
 *      &lt;/validators&gt;
 *  &lt;/field&gt;
 *  </pre>
 * Note that general principles of {@link com.smartgwt.client.data.DataSource#getOperationBindings
 * DataSource.operationBindings} also apply, so you have the 
 * complete control over which operations end up being executed via scriplets. For example you can
 * 
 * declare an <code>operationBinding</code> with no <code>operationId</code> to affect the default
 * 
 *  behavior of an operation. So if all update operations in a DataSource need to do a specific 
 *  security check, you can just do:
 *  <pre>
 *  &lt;operationBinding operationType="update"&gt;
 *      &lt;script&gt;
 *          // add a security check, update related records, etc
 *      &lt;/script&gt;
 *  &lt;/operationBinding&gt;
 *  </pre>
 * Scriptlets are automatically recompiled when you change the .ds.xml file - just reload the page
 *  and the Smart GWT Server Framework automatically notices the modified DataSource file and
 *  uses the new scriptlets. Same applies to the scripts declared in .app.xml files.
 *  <P>
 * Server Scripting is a great way to connect to an existing Java server API. You may have your
 * existing 
 * server API and .ds.xml files that contain brief bits of scripts connecting DataSource
 * operations 
 *  to the existing API and that's it.
 *  <P>
 *  <b>Declaring Scriptlet Language</b>
 *  <P>
 * You can set the default system-wide language in {@link
 * com.smartgwt.client.docs.Server_properties server.properties}
 *  by setting
 *  <code>script.defaultLanguage</code>:
 *  <pre>
 *      script.defaultLangauge: "groovy"
 *  </pre>
 * Alternatively, anywhere a scriptlet is allowed, you can use the "language" attribute to declare
 *  the language.  For example:
 *  <pre>
 *     &lt;operationBindings&gt;
 *        &lt;operationBinding operationType="add"&gt;
 *            &lt;script language="groovy"&gt;
 *               ... Groovy code ...
 *            &lt;/script&gt;
 *        &lt;/operationBinding&gt;
 *     &lt;/operationBindings&gt;
 *  </pre>
 *  <h3>Error Reporting</h3>
 *  <P>
 *  If your scriptlet crashes, this is reported in the server-side log along with the line number
 *  of the crash.  
 *  <pre>
 *       &lt;!-- crash will be reported at line 1 --&gt;
 *       &lt;script&gt;crash()&lt;/script&gt;
 * 
 *       &lt;!-- crash will be reported at line 2 --&gt;
 *       &lt;script&gt;
 *           crash()
 *       &lt;/script&gt;
 *  </pre>
 * It's common practice to use a CDATA tag so that XML-special characters such as &lt; do not have
 * to be
 * quoted as &amp;lt;.  When doing this, be aware that the line numbering will still start <b>from
 * the
 *  &lt;script&gt; tag</b>, not the CDATA tag.  For example:
 *  <pre>
 *       &lt;!-- crash will be reported at line 3 --&gt;
 *       &lt;script&gt;
 *           &lt;![CDATA[ 
 *              5 < crash()
 *           ]]&gt;
 *       &lt;/script&gt;
 * 
 *       &lt;!-- crash will be reported at line 2 --&gt;
 *       &lt;script&gt;&lt;![CDATA[ 
 *            5 < crash()
 *       ]]&gt;&lt;/script&gt;
 *  </pre>
 *  <P>
 *  <h3>Java Imports</h3>
 *  <P>
 *  You can import Java libraries by placing a &lt;scriptImport&gt; tag immediately before a
 *  &lt;script&gt; or &lt;serverCondition&gt; tag, like so:
 *  <pre>
 *      &lt;scriptImport&gt;javax.servlet.http.*&lt;/scriptImport&gt;
 *      &lt;script language="groovy"&gt;
 *          String sessionId = session.getId();
 *          ...
 *  </pre>
 *  There is also a system-wide set of default imports:
 *  <pre>
 *  java.util.*
 *  <release13>javax</release13><release14>jakarta</release14>.servlet.http.*
 *  com.isomorphic.base.Config
 *  com.isomorphic.util.*
 *  com.isomorphic.datasource.*
 *  com.isomorphic.rpc.RPCManager
 *  </pre>
 * You can override these in {@link com.smartgwt.client.docs.Server_properties server.properties}
 * via the property
 * <code>script.defaultImports</code>, which takes a comma- or space-separated list of packages or
 *  classes (like the above).
 *  <P>
 *  Dynamic languages such as Groovy or JavaScript allow you to place an import inside the script
 *  itself as well.
 *  <p>
 *  <b>NOTE:</b> If you are using Javascript as your scripting language, see the "Javascript"
 *  section below, and especially the discussion of GraalVM, for important caveats regarding 
 *  Java imports
 *  <P>
 *  <h3>Available Languages</h3>
 *  <P>
 * The Oracle JDK and JRE <a
 * href='https://docs.oracle.com/javase/10/scripting/java-scripting-api.htm#JSJSG109'
 * target='_blank'>include support for JavaScript scripting via the Nashorn engine</a>.
 *  Note that Nashorn was removed from Oracle and OpenJDK JVMs as of Java 15.  See the 
 *  "JavaScript" section at the end of this article for details of the options available if you 
 *  are using Java 15 or later.
 *  <p>
 *  For convenience, Smart GWT also bundles a .jar providing Groovy support from 
 * <a href='http://www.groovy-lang.org/' target='_blank'>http://www.groovy-lang.org/</a>, which
 * uses the Apache license.  We also include
 *  a .jar file providing Java language support (however see below for limitations).  This
 *  implementation is based on the BSD-licensed Java.net implementation, but enhanced by
 *  Isomorphic to work around container-specific classloader issues that arise when running Java
 *  language scripting inside a servlet container and trying to reference common objects of the
 *  servlet API itself.  See {@link com.smartgwt.client.docs.SunNotice} for licensing information.
 *  <p>
 *  There are <b>many</b> other languages available, sometimes with multiple implementations, and
 *  they are best found via web search.  Making use of any available JSR223 language is as 
 *  straightforward as dropping the applicable JAR file into your project and then using the 
 *  name under which that language registers itself (from the language's documentation) as the
 *  <code>language</code> property of your script.
 *  <P>
 *  <b>NOTE:</b> There is a known problem using Smart GWT's built-in Java language scripting 
 *  with Tomcat version 7.0.53 and newer (including Tomcat 8.x versions).  The problem is a 
 *  classloader issue for which there is no obvious workaround.  For this reason, we recommend
 *  that you use Groovy if you wish to use Java as a scripting language: to a very large extent,
 *  Groovy is a superset of Java, so the great majority of scripted Java source will work
 *  unchanged if you just change the language definition from "java" to "groovy".  There is no
 *  need to learn or use any of the Groovy language features - you are simply using Groovy as 
 *  an evaluation engine for plain Java language script.  Of course, if you want to use "real" 
 *  Java, that is always available to you through the normal channels of 
 *  {@link com.smartgwt.client.docs.serverds.OperationBinding#serverObject DMI} and 
 *  {@link com.smartgwt.client.docs.serverds.DataSource#serverConstructor custom datasources}.
 *  <p>
 *  A full description of the differences between Groovy and Java is 
 *  <a href=http://groovy-lang.org/differences.html>here</a>
 *  <P>
 *  <h3>Standard Headers &amp; Footers</h3>
 *  <P>
 *  You can define system-wide headers and footers for each language - code that is added before
 *  and after scriptlets wherever it is defined, and can set up variables or functions you use
 *  often.  To define the location of header and footer files, set
 * <code>script.<i>languageName</i>.header</code> and
 * <code>script.<i>languageName</i>.footer</code>
 *  in server.properties.  For example, these settings:
 *  <pre>
 *    script.groovy.header: $webRoot/shared/header.groovy
 *    script.groovy.footer: $webRoot/shared/footer.groovy
 *  </pre>
 * would add the Groovy fragments found in header.groovy and footer.groovy to beginning and end of
 * every
 *  scriptlet that declares language="groovy" (or declares no language if the default engine is
 *  "groovy").
 *  <P>
 *  <b>NOTE</b>: most scripting engines are available under several language names.  For example,
 *  the Nashorn JavaScript engine registers both "javascript" and "ecmascript" as well as a few
 * variations on letter case.  When using the "language" attribute on script tags, the exact value
 *  supplied is used to look up header and footer files via server.properties.  This means a
 * language setting of "javascript" will find different header and footer files from a language of
 *  "JavaScript" even though both will execute via Nashorn.
 *  <P>
 *  <h3>Java scriptlets and the default script wrapper</h3>
 *  <P>
 *  Although it's not usually considered a "scripting language", using the Java language for
 * scriplets has the advantage that developers do not need to understand two languages in order to
 *  modify server-side code.  However, using Java for scripting presents special challenges,
 *  because unlike true scripting languages, in Java a piece of code cannot be compiled unless it
 *  forms a valid class definition.  
 *  <P>
 *  For this reason, by default every Java scriplet has an implicit wrapper added around it which
 *  makes it into a class definition of a trivial class with one method, and your scriptlet code
 *  forms the body of that method, after a series of local variables have been set up to allow
 *  convenient access to context variables.  The header and footer files you've defined, if any,
 *  appear before and after your scriptlet, still within the method body.
 *  <P>
 *  This makes Java viable as a scripting language despite its verbosity - if the actual business
 *  logic to be executed consists of just a few lines of Java, your overall scriptlet will be only
 *  that long instead of being forced to contain a complete class definition.
 *  <P>
 *  The automatic wrapping of Java code can be disabled by setting
 *  <code>script.java.useDefaultScriptWrapper</code> to false in server.properties.  In this case
 *  any scriptlet must contain a valid class definition like the below - context variables need to
 *  be manually retrieved from the ScriptContext object instead of being automatically
 *  available as local variables, and the attribute "evalResult" is used to return data in lieu of
 *  using a <code>return</code> statement.
 *  <P>
 *  <pre>
 *  class Temp {
 *      private static ScriptContext ctx;
 *      public static void setScriptContext(ScriptContext context) {
 *          ctx = context;
 *      }
 *      public static void main(String[] args) {
 *          String result = "Hello World!";
 *          ctx.setAttribute("evalResult", result, 
 *                           ScriptContext.ENGINE_SCOPE);
 *      }
 *  }
 *  </pre>
 *  All scriptlets must also import javax.script.ScriptContext.  For obvious reasons setting
 *  <code>useDefaultScriptWrapper</code> to false is not recommended.
 *  <P>
 *  <h3>Returning values and JavaScript</h3>
 *  <P>
 *  Scriptlets written in Java <b>must</b> use a <code>return</code> statement to return a
 *  result from the scriptlet.  Scriptlets written in JavaScript <b>must not</b> use a
 *  <code>return</code> as Nashorn will report this as an error - the JavaScript code is not
 *  executed in the scope of a function, and only functions can <code>return</code>.
 *  <P>
 *  Instead, JavaScript scriptlets should simply end with a statement indicating the value
 *  they would like to return.  For example:
 *  <pre>
 *      // if used as the last line, the scriptlet 
 *      // returns the result of dsRequest.execute();
 *      dsRequest.execute();
 * 
 *      // if you already have the value as a variable,
 *      // just end with the variable name plus semicolon
 *      var dsResponse = dsRequest.execute();
 *      dsResponse;
 * 
 *      // add a line like this to force returning null 
 *      // instead of the result of the previous line of code
 *      null;
 *  </pre>
 *  Groovy makes the <code>return</code> statement optional, and like JavaScript, will take the
 *  value of the last statement as the returned value if there is no explicit
 *  <code>return</code>.
 *  <P>
 *  Other languages supported by JSR223 may have other special semantics for returning data - see
 *  their documentation for details.
 *  <P>
 *  <h3>Available context variables for scriptlets</h3>
 *  <P>
 *  Context variables that are available to a scriptlet are explained in the documentation for the
 *  particular property where a scriptlet may be declared, for example,
 * {@link com.smartgwt.client.docs.serverds.OperationBinding#script OperationBinding.script} and
 * {@link com.smartgwt.client.docs.serverds.Validator#serverCondition Validator.serverCondition}.
 *  <P>
 *  In most JSR223 languages, context variables are available as ordinary local variables and you
 *  can simply refer to them directly in your scriptlet.  This includes Java, so long as
 *  useDefaultScriptWrapper is left in its default setting (see above).
 *  <p>
 *  <h3>Caching</h3>
 *  <p>
 *  JSR223 script calls involve an overhead; the exact overhead depends on the language being 
 *  used, including whether that language requires a compilation step, and the capability of 
 *  the hardware.  Our testing in this area shows a cost of between 10 and 100ms per call, 
 *  running Smart GWT Server on a VM hosted on a capable but not spectacular machine by 
 *  the standards of early 2020's (AMD Ryzen 7 2700 CPU).
 *  <p>
 *  For this reason, Smart GWT implements script caching for any JSR223 script language that
 *  supports pre-compilation (ie, implements the <code>javax.script.Compilable</code> interface).
 *  Pre-compiled scripts are cached per-DataSource, so if script performance is important to
 *  you, you should ensure you are using dataSource pooling (covered in 
 * {@link com.smartgwt.client.docs.ServerDataSourceImplementation this overview}).  DataSource
 * pooling is a good 
 *  idea anyway, but it is especially important if you need script caching, because without 
 *  pooling, DataSource instances are created from scratch each time they are needed, so any
 *  cached script will only be cached for the life of a server turnaround.
 *  <p>
 *  As you would expect, caching makes the second and subsequent calls to a given script 
 *  significantly quicker.  In-house, we test our script support with two JSR223 languages: 
 *  JavaScript (the Nashorn engine built into the JVM in Java releases up to 14), and Groovy.
 *  Switching caching on makes JavaScript calls 5-6 times faster, and Groovy calls 50 or more 
 *  times faster.
 *  <p>
 *  Script caching is on by default.  You can switch it off system-wide with the following
 *  <code>server.properties</code> setting:<pre>
 *     scripting.cache.compilable.scripts: false
 *  </pre>
 *  <p>
 *  <h3>Relative Performance</h3>
 *  <p>
 *  Whether caching is on or off, script performance differs from language to language.  Our
 *  automated tests show that, while JavaScript calls have a small fixed overhead (about 5ms
 *  per call, with caching switched on, on the hardware specs mentioned in the previous section), 
 *  Groovy calls are <b>much</b> quicker: when measured with instrumented code using Java's 
 *  <code>System.nanoTime()</code> API, cached Groovy scripts have an average invocation time 
 *  of around 80 microseconds, or about one twelfth of a millisecond.  This tiny overhead is 
 *  because Groovy is a JVM language that compiles to the same bytecode as the equivalent Java,
 *  so we would expect similarly good performance from other JVM languages like 
 * <a href='https://kotlinlang.org' target='_blank'>Kotlin</a> or <a href='https://www.jruby.org'
 * target='_blank'>JRuby</a>, 
 *  both of which also have a JSR223 implementation.
 *  <p>
 *  For this reason, we recommend using Groovy as a scripting language in cases where the best 
 *  performance is required, such as "inner-loop" cases like 
 * {@link com.smartgwt.client.docs.serverds.DataSourceField#fieldValueScript fieldValueScript}s
 * (which are called for every field
 *  on which they are defined, for every record in a resultset).  However, see the following
 *  section on Javascript for important extra information about this.
 *  <p>
 *  <h3>Javascript</h3>
 *  <p>
 *  In versions of Java up to JDK 14, there is a Javascript implmentation - Nashorn - built 
 *  into the JVM.  This was removed in version 15, but at the same time, OpenJDK made a 
 *  standalone version of Nashorn available.  Since this standalone version works without 
 *  problems in pre-15 JDKs (ie, it does not clash with the built-in Nashorn), we ship it as
 *  part of the product.  This means that Javascript is an option out-of-the-box, regardless 
 *  of the Java version you are using (assuming you are not using a version earlier than 1.6)
 *  <p>
 *  An alternative to the standalone Nashorn implementation is to switch from the regular 
 *  Oracle or OpenJDK JVM, to GraalVM, detailed below.  And there are other options too: 
 *  Mozilla Rhino is still maintained and does work with Smart GWT's scripting feature 
 *  (though it is slow and lacking in features compared to Nashorn); non-Oracle JVMs may 
 *  implement other Javascript engines; and JSR223 is an open standard so there is nothing to 
 *  stop people from creating their own ScriptEngine implementations based on whichever 
 *  Javascript engine they favor.  From a Smart GWT server-scripting perspective, if a script
 *  is marked with a <code>language</code> of "javascript", "Javascript", JavaScript" or 
 *  "ecmascript", we try to find an engine registered with any of those short names (ie, if the
 *  language is "JavaScript" but there is no ScriptEngine registered with that short name, we 
 *  will also try "javascript", "Javascript" and "ecmascript" before giving up).
 *  <p>
 *  <h4>GraalVM</h4>
 *  GraalVM is Oracle's "polyglot" VM, which has support for Javascript as a first-class 
 *  language.  You can use GraalVM instead of a regular JVM (the JVM core of it is OpenJDK), 
 *  and access its Javascript support through a JSR223 interface (there are more direct ways 
 *  to use Javascript in GraalVM, but this is how you use it with Smart GWT's scripting 
 *  feature).  This approach works fine with Smart GWT's scripting support, and moreover it
 *  is <b>much</b> faster than the Nashorn engine.  In fact, it has the same tiny call overhead
 *  as Groovy - about 80 microseconds in local testing - and so is suitable for use in even the
 *  most intensive use cases where we previously have recommended that only Groovy should be 
 *  used.
 *  <p>
 *  However, this very significant reduction in call overhead - from around 15ms per call in 
 *  Nashorn in our local testing, to under 0.1ms in GraalJS - comes at the cost of reduced
 *  flexibility in importing Java classes.  By default, Smart GWT server scripts written in
 *  Javascript automatically import a number of useful or commonly-used Java packages - for 
 *  example, <code>java.util.*</code>, <code>com.isomorphic.util.*</code> and 
 *  <code><release13>javax</release13><release14>jakarta</release14>.servlet.http.*</code>.
 *  This ability to import whole packages is a Mozilla Rhino compatibility feature that is 
 *  discouraged by the GraalVM team, and if you use it, call overhead times increase 
 *  dramatically, to the point where there is no performance advantage over Nashorn.
 *  <p>
 *  For this reason, we support switching off Mozilla compatibility via a 
 *  <code>server.properties</code> flag:<pre>
 *     script.javascript.useMozillaCompat: false
 *  </pre>
 *  If you set that flag true, server scripts written in Javascript will:<ul>
 *  <li>Not load the special <code>nashorn:mozilla-compat.js</code> script (which, in GraalVM,
 *  has a small beneficial effect on call overhead times by itself)</li>
 *  <li>Not use the Rhino-specific <code>importClass</code> and <code>importPackage</code> APIs.
 *  Instead, class-specific imports will be created as aliases using the native Nashorn (and 
 *  GraalJS) technique, like this:<pre>
 *      var System = Java.type('java.lang.System')
 *  </pre>Wildcard package imports like <code>java.lang.*</code> will simply be skipped.  Of 
 *  course, depending on various factors, skipping wildcard imports may be too inconvenient to 
 *  be practical in your use case.  In that case there is currently no alternative other than
 * to leave <code>mozillaCompat</code> set to true and live with the additional call overhead</li>
 *  </ul>
 *  At the time of writing, GraalVM is available based on OpenJDK 17, 21 and 23, though there
 *  are also older versions still downloadable based on JDK 11; if you use the OpenJDK 11 
 *  version, or you continue to deploy the standalone nashorn-core library mentioned above, 
 *  this means you have both Nashorn and GraalJS available.  In this case, there are 
 *  conflicting registrations - a number of variations on "javascript", "js" and "ecmascript" 
 *  are registered for both Nashorn and GraalVM.  In our testing, the GraalVM registrations 
 *  always win in this situation, but if you want to be absolutely sure of picking up a 
 *  particular engine, specify lanaguage "nashorn" for Nashorn and "graal.js" for GraalJS.  
 * GraalVM homepage: <a href='https://www.graalvm.org/'
 * target='_blank'>https://www.graalvm.org/</a>
 *  <p>
 *  It is also possible to implement GraalJS (the Javascript engine from GraalVM) directly on
 *  a regular Oracle or OpenJDK JVM (though note, in local testing we saw some but not all of
 *  the performance advantages of switching to the full GraalVM - call overheads are reduced to
 *  sub-millisecond, but do not get near the ~100 microsecond overhead that we saw with the
 *  full GraalVM).  Implementing GraalJS on a regular JVM requires adding the following JARs
 *  from the GraalVM project (all available from Maven Central):
 *  <ul>
 *  <li><b>org.graalvm.js</b>: js-scriptengine, js-language</li>
 *  <li><b>org.graalvm.polyglot</b>: polyglot</li>
 *  <li><b>org.graalvm.truffle</b>: truffle-api, truffle-runtime, truffle-compiler</li>
 *  <li><b>org.graalvm.regex</b>: regex</li>
 *  <li><b>org.graalvm.sdk</b>: collections, nativeimage, word</li>
 *  <li><b>org.graalvm.shadowed</b>: icu4j</li>
 *  </ul>
 *  See {@link com.smartgwt.client.docs.JavaModuleDependencies} for the complete list.
 *  <p>
 *  <h4>GraalJS 24.x Configuration</h4>
 *  <P>
 *  <b>Important:</b> GraalJS 24.x removed the deprecated <code>js.nashorn-compat</code>
 *  option that was available in earlier versions. If you are upgrading from GraalJS 23.x
 *  or earlier, remove any <code>-Dpolyglot.js.nashorn-compat=true</code> JVM flags as
 *  they will cause startup failures in GraalJS 24.x.
 *  <P>
 *  In GraalJS 24.x, Java interop is enabled by default when running through the JSR-223
 *  ScriptEngine API (the mode used by Smart GWT's server scripting feature).
 *  The <code>Java.type()</code> API works without additional configuration.
 *  <P>
 *  If you see interpreter-only mode warnings, you can suppress them with:
 *  <pre>
 *      -Dpolyglot.engine.WarnInterpreterOnly=false
 *  </pre>
 *  <P>
 *  For further information on GraalJS configuration, see
 * <a href='https://www.graalvm.org/latest/reference-manual/js/RunOnJDK' target='_blank'>Running
 * GraalJS on JDK</a>
 *  and
 * <a href='https://www.graalvm.org/latest/reference-manual/js/NashornMigrationGuide'
 * target='_blank'>Nashorn Migration Guide</a>.
 *  <p>
 * @see com.smartgwt.client.docs.serverds.DataSource#transformRequestScript
 * @see com.smartgwt.client.docs.serverds.DataSource#transformRawResponseScript
 * @see com.smartgwt.client.docs.serverds.DataSource#transformResponseScript
 * @see com.smartgwt.client.docs.serverds.DataSourceField#fieldValueScript
 * @see com.smartgwt.client.docs.serverds.OperationBinding#transformRequestScript
 * @see com.smartgwt.client.docs.serverds.OperationBinding#transformRawResponseScript
 * @see com.smartgwt.client.docs.serverds.OperationBinding#transformResponseScript
 */
public interface ServerScript {
}
