Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… rhino binding global context (#110)
  • Loading branch information
vharseko authored Apr 25, 2024
1 parent 8129dc7 commit d53d0b8
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 98 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ]
os: [ 'ubuntu-latest', 'macos-12', 'windows-latest' ]
java: [ '8', '11', '17', '21' ]
fail-fast: false
steps:
Expand Down
2 changes: 1 addition & 1 deletion commons/rest/api-descriptor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<packaging>bundle</packaging>

<properties>
<rhino.version>1.7.12</rhino.version>

</properties>

<build>
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
<jackson.version>2.14.3</jackson.version>
<slf4j.version>1.7.36</slf4j.version>
<swagger.version>1.6.11</swagger.version>
<rhino.version>1.7.14</rhino.version>
</properties>

<prerequisites>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
/*
* DO NOT REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2015 ForgeRock AS. All rights reserved.
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
Expand All @@ -20,6 +16,8 @@
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright 2015-2016 ForgeRock AS.
*/

package org.forgerock.script.exception;
Expand All @@ -35,6 +33,13 @@ public class ScriptCompilationException extends ScriptException {
/** Serializable class a version number. */
static final long serialVersionUID = 1L;

/**
* Constructs a new exception with the specified detail message.
*/
public ScriptCompilationException(String message) {
super(message);
}

/**
* Constructs a new exception with the specified detail message and cause.
*/
Expand All @@ -50,4 +55,4 @@ public ScriptCompilationException(String message, Exception cause, String fileNa
super(message, fileName, lineNumber, columnNumber);
initCause(cause);
}
}
}
8 changes: 4 additions & 4 deletions script/javascript/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.rhino</artifactId>
<version>1.7R4_1</version>
<version>${rhino.version}_2</version>
</dependency>
<dependency>
<groupId>org.eclipse.wst.jsdt.debug</groupId>
Expand Down Expand Up @@ -130,12 +130,12 @@
<scope>test</scope>
</dependency>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=379385 -->
<dependency>
<!--dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7.12</version>
<version>${rhino.version}</version>
<scope>test</scope>
</dependency>
</dependency-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
/*
* DO NOT REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2014 ForgeRock AS. All rights reserved.
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
Expand All @@ -20,6 +16,8 @@
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright 2012-2016 ForgeRock AS.
*/

package org.forgerock.script.javascript;
Expand Down Expand Up @@ -97,6 +95,9 @@ public class RhinoScript implements CompiledScript {
/** The CommonJS module builder for Require instances. */
private final RequireBuilder requireBuilder;

/** Indicates if this script instance should use the shared scope. */
private final boolean sharedScope;

public static final Global GLOBAL = new Global();

static {
Expand All @@ -112,62 +113,43 @@ public void quit(Context cx, int exitCode) {
}
}

/** Indicates if this script instance should use the shared scope. */
private final boolean sharedScope;

/**
* Compiles the JavaScript source code into an executable script. If
* {@code useSharedScope} is {@code true}, then a sealed shared scope
* containing standard JavaScript objects (Object, String, Number, Date,
* etc.) will be used for script execution; otherwise a new unsealed scope
* will be allocated for each execution.
*
*
* @param compiledScript
* the source code of the JavaScript script.
* @param sharedScope
* if {@code true}, uses the shared scope, otherwise allocates
* new scope.
* @throws ScriptException
* if there was an exception encountered while compiling the
* script.
* @param name the name of the script
* @param compiledScript the to-be-executed compiled script
* @param engine the parent script engine
* @param requireBuilder The CommonJS module builder for Require instances.
* @param sharedScope Indicates if this script instance should use the shared scope. If {@code useSharedScope} is
* {@code true}, then a sealed shared scope containing standard JavaScript objects (Object, String, Number, Date,
* etc.) will be used for script execution; otherwise a new unsealed scope will be allocated for each execution.
*/
public RhinoScript(String name, Script compiledScript, final RhinoScriptEngine engine, RequireBuilder requireBuilder,
boolean sharedScope) throws ScriptException {
boolean sharedScope) {
this.scriptName = name;
this.sharedScope = sharedScope;
this.engine = engine;
this.requireBuilder = requireBuilder;
Context cx = Context.enter();
cx.setLanguageVersion(Context.VERSION_ES6);
try {
scriptScope = getScriptScope(cx);
script = compiledScript;
// script = cx.compileString(source, name, 1, null);
} catch (RhinoException re) {
throw new ScriptException(re.getMessage());
} finally {
Context.exit();
}
}

/**
* TEMPORARY
*
* @param name the name of the script
* @param engine the parent script engine
* @param requireBuilder The CommonJS module builder for Require instances.
* @param sharedScope Indicates if this script instance should use the shared scope. If {@code useSharedScope} is
* {@code true}, then a sealed shared scope containing standard JavaScript objects (Object, String, Number, Date,
* etc.) will be used for script execution; otherwise a new unsealed scope will be allocated for each execution.
*/
public RhinoScript(String name, final RhinoScriptEngine engine, RequireBuilder requireBuilder, boolean sharedScope)
throws ScriptException {
this.scriptName = name;
this.sharedScope = sharedScope;
this.engine = engine;
this.requireBuilder = requireBuilder;
Context cx = Context.enter();
try {
scriptScope = getScriptScope(cx);
script = null;// cx.compileReader(reader, name, 1, null);
} catch (RhinoException re) {
throw new ScriptException(re);
} finally {
Context.exit();
}
public RhinoScript(String name, final RhinoScriptEngine engine, RequireBuilder requireBuilder, boolean sharedScope) {
this(name, null, engine, requireBuilder, sharedScope);
}

/**
Expand All @@ -184,7 +166,6 @@ private ScriptableObject getStandardObjects(final Context context) {
if (!sharedScope) {
// somewhat expensive
ScriptableObject scope = context.initStandardObjects();
installRequire(context, scope);
return scope;
}
// lazy initialization race condition is harmless
Expand All @@ -203,20 +184,13 @@ private ScriptableObject getStandardObjects(final Context context) {
}
}
addLoggerProperty(scope);
installRequire(context, scope);
// seal the whole scope (not just standard objects)
scope.sealObject();
topSharedScope = scope;
}
return topSharedScope;
}

// install require function per unofficial CommonJS author documentation
// https://groups.google.com/d/msg/mozilla-rhino/HCMh_lAKiI4/P1MA3sFsNKQJ
private void installRequire(final Context context, final ScriptableObject scope) {
requireBuilder.createRequire(context, scope).install(scope);
}

/**
* Get the scope scriptable re-used for this script Holds common
* functionality such as the logger
Expand Down Expand Up @@ -260,6 +234,7 @@ public Object eval(final org.forgerock.services.context.Context ctx, Bindings re
throws ScriptException {

Context context = Context.enter();
context.setLanguageVersion(Context.VERSION_ES6);
try {
Scriptable outer = context.newObject(getStandardObjects(context));

Expand Down Expand Up @@ -303,43 +278,44 @@ public Object eval(final org.forgerock.services.context.Context ctx, Bindings re
}

outer.setPrototype(scriptScope); // script level context and
// standard objects included with
// every box
// standard objects included with
// every box
outer.setParentScope(null);
Scriptable inner = context.newObject(outer); // inner transient
// scope for new
// properties
// scope for new
// properties
inner.setPrototype(outer);
inner.setParentScope(null);

// install require function per unofficial CommonJS author documentation
// https://groups.google.com/d/msg/mozilla-rhino/HCMh_lAKiI4/P1MA3sFsNKQJ
requireBuilder.createRequire(context, inner).install(inner);

final Script scriptInstance = null != script ? script : engine.createScript(scriptName);
Object result = Converter.convert(scriptInstance.exec(context, inner));
return result; // Context.jsToJava(result, Object.class);
} catch (ScriptException e) {
throw e;
} catch (WrappedException e) {
if (e.getWrappedException() instanceof ResourceException) {
throw new ScriptThrownException(e.getMessage(), e.sourceName(), e.lineNumber(), e.columnNumber(),
((ResourceException) e.getWrappedException()).toJsonValue().getObject());
throw getScriptExecutionGenerator().newScriptThrownException(e,
((ResourceException)e.getWrappedException()).toJsonValue().getObject());
} else {
ScriptException exception =
new ScriptThrownException(e.getMessage(), e.sourceName(), e.lineNumber(), e.columnNumber(),
e.getWrappedException());
ScriptException exception = getScriptExecutionGenerator().newScriptThrownException(e,
e.getWrappedException());
exception.initCause(e.getWrappedException());
throw exception;
}
} catch (JavaScriptException e) {
logger.debug("Failed to evaluate {} script.", scriptName, e);
ScriptThrownException exception =
new ScriptThrownException(e.getMessage(), e.sourceName(), e.lineNumber(), e.columnNumber(),
Converter.convert(e.getValue()));
ScriptThrownException exception = getScriptExecutionGenerator().newScriptThrownException(e,
Converter.convert(e.getValue()));
exception.initCause(e);
throw exception;
} catch (RhinoException e) {
logger.debug("Failed to evaluate {} script.", scriptName, e);
// some other runtime exception encountered
final ScriptException exception =
new ScriptException(e.getMessage(), e.sourceName(), e.lineNumber(), e.columnNumber());
final ScriptException exception = getScriptExecutionGenerator().newScriptException(e);
exception.initCause(e);
throw exception;
} catch (Exception e) {
Expand All @@ -351,6 +327,10 @@ public Object eval(final org.forgerock.services.context.Context ctx, Bindings re
}
}

private RhinoScriptEngine.ScriptExceptionGenerator getScriptExecutionGenerator() {
return engine.getScriptExceptionGenerator();
}

private static class InnerClassLoader extends SecureClassLoader {

public InnerClassLoader(ClassLoader parent) {
Expand All @@ -372,4 +352,4 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
}
}

}
}
Loading

0 comments on commit d53d0b8

Please sign in to comment.