[JS SCRIPTING] moved the javascript engines to a separate module

This commit is contained in:
Vitaliy.Tikhonov
2019-08-30 13:48:41 +03:00
committed by romanart
parent bf0b4f6878
commit f13e05de7d
8 changed files with 73 additions and 31 deletions
+30
View File
@@ -0,0 +1,30 @@
import org.gradle.internal.os.OperatingSystem
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compile(project(":compiler:util"))
compile(project(":js:js.ast"))
compile(project(":js:js.translator"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
val currentOs = OperatingSystem.current()
when {
currentOs.isWindows -> {
val suffix = if (currentOs.toString().endsWith("64")) "_64" else ""
compileOnly("com.eclipsesource.j2v8:j2v8_win32_x86$suffix:4.6.0")
}
currentOs.isMacOsX -> compileOnly("com.eclipsesource.j2v8:j2v8_macosx_x86_64:4.6.0")
currentOs.run { isLinux || isUnix } -> compileOnly("com.eclipsesource.j2v8:j2v8_linux_x86_64:4.8.0")
else -> logger.error("unsupported platform $currentOs - can not compile com.eclipsesource.j2v8 dependency")
}
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.engine
interface ScriptEngine {
fun <T> eval(script: String): T
fun evalVoid(script: String)
fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T
fun loadFile(path: String)
fun release()
fun <T> releaseObject(t: T)
fun saveState()
fun restoreState()
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.engine
import jdk.nashorn.api.scripting.NashornScriptEngineFactory
import jdk.nashorn.internal.runtime.ScriptRuntime
import javax.script.Invocable
class ScriptEngineNashorn : ScriptEngine {
private var savedState: Map<String, Any?>? = null
// TODO use "-strict"
private val myEngine = NashornScriptEngineFactory().getScriptEngine("--language=es5", "--no-java", "--no-syntax-extensions")
@Suppress("UNCHECKED_CAST")
override fun <T> eval(script: String): T {
return myEngine.eval(script) as T
}
override fun evalVoid(script: String) {
myEngine.eval(script)
}
@Suppress("UNCHECKED_CAST")
override fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T {
return (myEngine as Invocable).invokeMethod(obj, name, *args) as T
}
override fun loadFile(path: String) {
evalVoid("load('${path.replace('\\', '/')}');")
}
override fun release() {}
override fun <T> releaseObject(t: T) {}
private fun getGlobalState(): MutableMap<String, Any?> = eval("this")
override fun saveState() {
savedState = getGlobalState().toMap()
}
override fun restoreState() {
val globalState = getGlobalState()
val originalState = savedState!!
for (key in globalState.keys) {
globalState[key] = originalState[key] ?: ScriptRuntime.UNDEFINED
}
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.js.engine
import com.eclipsesource.v8.V8
import com.eclipsesource.v8.V8Array
import com.eclipsesource.v8.V8Object
import com.eclipsesource.v8.utils.V8ObjectUtils
import java.io.File
class ScriptEngineV8(LIBRARY_PATH_BASE: String) : ScriptEngine {
override fun <T> releaseObject(t: T) {
(t as? V8Object)?.release()
}
private var savedState: List<String>? = null
override fun restoreState() {
val scriptBuilder = StringBuilder()
val globalState = getGlobalPropertyNames()
val originalState = savedState!!
for (key in globalState) {
if (key !in originalState) {
scriptBuilder.append("this['$key'] = void 0;\n")
}
}
evalVoid(scriptBuilder.toString())
}
private fun getGlobalPropertyNames(): List<String> {
val v8Array = eval<V8Array>("Object.getOwnPropertyNames(this)")
@Suppress("UNCHECKED_CAST") val javaArray = V8ObjectUtils.toList(v8Array) as List<String>
v8Array.release()
return javaArray
}
override fun saveState() {
if (savedState == null) {
savedState = getGlobalPropertyNames()
}
}
private val myRuntime: V8 = V8.createV8Runtime("global", LIBRARY_PATH_BASE)
@Suppress("UNCHECKED_CAST")
override fun <T> eval(script: String): T {
return myRuntime.executeScript(script) as T
}
override fun evalVoid(script: String) {
return myRuntime.executeVoidScript(script)
}
@Suppress("UNCHECKED_CAST")
override fun <T> callMethod(obj: Any, name: String, vararg args: Any?): T {
if (obj !is V8Object) {
throw Exception("InteropV8 can deal only with V8Object")
}
val runtimeArray = V8Array(myRuntime)
val result = obj.executeFunction(name, runtimeArray) as T
runtimeArray.release()
return result
}
override fun loadFile(path: String) {
myRuntime.executeVoidScript(File(path).bufferedReader().use { it.readText() }, path, 0)
}
override fun release() {
myRuntime.release()
}
}
class ScriptEngineV8Lazy(LIBRARY_PATH_BASE: String) : ScriptEngine {
override fun <T> eval(script: String) = engine.eval<T>(script)
override fun saveState() = engine.saveState()
override fun evalVoid(script: String) = engine.evalVoid(script)
override fun <T> callMethod(obj: Any, name: String, vararg args: Any?) = engine.callMethod<T>(obj, name, args)
override fun loadFile(path: String) = engine.loadFile(path)
override fun release() = engine.release()
override fun <T> releaseObject(t: T) = engine.releaseObject(t)
override fun restoreState() = engine.restoreState()
private val engine by lazy { ScriptEngineV8(LIBRARY_PATH_BASE) }
}