135 lines
5.0 KiB
Kotlin
Executable File
135 lines
5.0 KiB
Kotlin
Executable File
/*
|
|
* Copyright (c) 2005, 2006, 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 com.script.rhino
|
|
|
|
import com.script.CompiledScript
|
|
import com.script.ScriptEngine
|
|
import com.script.ScriptException
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.asContextElement
|
|
import kotlinx.coroutines.withContext
|
|
import org.mozilla.javascript.Context
|
|
import org.mozilla.javascript.ContinuationPending
|
|
import org.mozilla.javascript.JavaScriptException
|
|
import org.mozilla.javascript.RhinoException
|
|
import org.mozilla.javascript.Script
|
|
import org.mozilla.javascript.Scriptable
|
|
import java.io.IOException
|
|
import kotlin.coroutines.CoroutineContext
|
|
|
|
/**
|
|
* Represents compiled JavaScript code.
|
|
*
|
|
* @author Mike Grogan
|
|
* @since 1.6
|
|
*/
|
|
internal class RhinoCompiledScript(
|
|
private val engine: RhinoScriptEngine,
|
|
private val script: Script
|
|
) : CompiledScript() {
|
|
|
|
override fun getEngine(): ScriptEngine {
|
|
return engine
|
|
}
|
|
|
|
override fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any? {
|
|
val cx = Context.enter() as RhinoContext
|
|
val previousCoroutineContext = cx.coroutineContext
|
|
if (coroutineContext != null && coroutineContext[Job] != null) {
|
|
cx.coroutineContext = coroutineContext
|
|
}
|
|
cx.allowScriptRun = true
|
|
cx.recursiveCount++
|
|
val result: Any?
|
|
try {
|
|
cx.checkRecursive()
|
|
val ret = script.exec(cx, scope)
|
|
result = engine.unwrapReturnValue(ret)
|
|
} catch (re: RhinoException) {
|
|
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
|
|
val msg: String = if (re is JavaScriptException) {
|
|
re.value.toString()
|
|
} else {
|
|
re.toString()
|
|
}
|
|
val se = ScriptException(msg, re.sourceName(), line)
|
|
se.initCause(re)
|
|
throw se
|
|
} finally {
|
|
cx.coroutineContext = previousCoroutineContext
|
|
cx.allowScriptRun = false
|
|
cx.recursiveCount--
|
|
Context.exit()
|
|
}
|
|
return result
|
|
}
|
|
|
|
override suspend fun evalSuspend(scope: Scriptable): Any? {
|
|
val cx = Context.enter() as RhinoContext
|
|
var ret: Any?
|
|
withContext(VMBridgeReflect.contextLocal.asContextElement()) {
|
|
cx.allowScriptRun = true
|
|
cx.recursiveCount++
|
|
try {
|
|
cx.checkRecursive()
|
|
try {
|
|
ret = cx.executeScriptWithContinuations(script, scope)
|
|
} catch (e: ContinuationPending) {
|
|
var pending = e
|
|
while (true) {
|
|
try {
|
|
@Suppress("UNCHECKED_CAST")
|
|
val suspendFunction = pending.applicationState as suspend () -> Any?
|
|
val functionResult = suspendFunction()
|
|
val continuation = pending.continuation
|
|
ret = cx.resumeContinuation(continuation, scope, functionResult)
|
|
break
|
|
} catch (e: ContinuationPending) {
|
|
pending = e
|
|
}
|
|
}
|
|
}
|
|
} catch (re: RhinoException) {
|
|
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
|
|
val msg: String = if (re is JavaScriptException) {
|
|
re.value.toString()
|
|
} else {
|
|
re.toString()
|
|
}
|
|
val se = ScriptException(msg, re.sourceName(), line)
|
|
se.initCause(re)
|
|
throw se
|
|
} catch (var14: IOException) {
|
|
throw ScriptException(var14)
|
|
} finally {
|
|
cx.allowScriptRun = false
|
|
cx.recursiveCount--
|
|
Context.exit()
|
|
}
|
|
}
|
|
return engine.unwrapReturnValue(ret)
|
|
}
|
|
|
|
} |