Skip to content

Commit

Permalink
✨ feat: Add module support
Browse files Browse the repository at this point in the history
  • Loading branch information
caoccao committed Nov 25, 2023
1 parent 72d29ad commit 42c7a29
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 9 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Javet Shell is a simple console or Android application that provides a Node.js f
Usage: Javet Shell options_list
Options:
--runtimeType, -r [V8] -> JS runtime type { Value should be one of [node, v8] }
--scriptName, -n [main.js] -> Script name { String }
--module, -m [false] -> Module
--scriptName, -s [main.js] -> Script name { String }
--help, -h -> Usage info
```
Expand Down
63 changes: 58 additions & 5 deletions console/src/main/kotlin/com/caoccao/javet/shell/JavetShell.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,68 @@

package com.caoccao.javet.shell

import com.caoccao.javet.enums.V8AwaitMode
import com.caoccao.javet.exceptions.JavetCompilationException
import com.caoccao.javet.exceptions.JavetExecutionException
import com.caoccao.javet.interop.V8Host
import com.caoccao.javet.interop.V8Runtime
import com.caoccao.javet.interop.callback.JavetBuiltInModuleResolver
import com.caoccao.javet.shell.constants.Constants
import com.caoccao.javet.shell.entities.Options
import com.caoccao.javet.shell.enums.ExitCode
import com.caoccao.javet.values.V8Value
import java.io.File
import java.util.*
import java.util.concurrent.TimeUnit

class JavetShell(
private val options: Options,
) {
fun run(): ExitCode {
) : Runnable {
@Volatile
private var quitting = true
private var thread: Thread? = null
private var v8Runtime: V8Runtime? = null

fun execute(): ExitCode {
println("${Constants.Application.NAME} v${Constants.Application.VERSION} (${options.jsRuntimeType.name} ${options.jsRuntimeType.version})")
println("Please input the script or press Ctrl+C to exit.")
println()
V8Host.getInstance(options.jsRuntimeType).createV8Runtime<V8Runtime>().use { v8Runtime ->
quitting = false
this.v8Runtime = v8Runtime
if (options.module) {
if (options.jsRuntimeType.isNode) {
v8Runtime.v8ModuleResolver = JavetBuiltInModuleResolver()
v8Runtime.getExecutor(
"""const process = require('process');
process.on('unhandledRejection', (reason, promise) => {
console.error();
console.error(reason.toString());
console.error();
});"""
).executeVoid()
} else {
v8Runtime.setPromiseRejectCallback { _, _, value ->
println()
println(value.toString())
println()
}
}
thread = Thread(this)
thread?.start()
}
Scanner(System.`in`).use { scanner ->
val sb = StringBuilder()
var isMultiline = false
while (true) {
while (!quitting) {
print(if (isMultiline) ">>> " else "> ")
try {
sb.appendLine(scanner.nextLine())
v8Runtime.getExecutor(sb.toString()).setResourceName(options.scriptName).execute<V8Value>()
v8Runtime
.getExecutor(sb.toString())
.setResourceName(File(options.scriptName).absolutePath)
.setModule(options.module)
.execute<V8Value>()
.use { v8Value ->
println(v8Value.toString())
}
Expand All @@ -57,7 +93,7 @@ class JavetShell(
println()
} catch (e: NoSuchElementException) {
println()
break
quitting = true
} catch (t: Throwable) {
sb.clear()
isMultiline = false
Expand All @@ -67,7 +103,24 @@ class JavetShell(
}
}
}
quitting = true
if (options.module) {
thread?.join()
thread = null
}
}
this.v8Runtime = null
return ExitCode.NoError
}

override fun run() {
while (!quitting) {
v8Runtime?.await(V8AwaitMode.RunOnce)
try {
TimeUnit.MILLISECONDS.sleep(Constants.Application.AWAIT_INTERVAL_IN_MILLIS)
} catch (t: Throwable) {
// Ignore
}
}
}
}
10 changes: 8 additions & 2 deletions console/src/main/kotlin/com/caoccao/javet/shell/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ fun main(args: Array<String>) {
ArgType.Choice<RuntimeType>(),
shortName = Constants.Options.JS_RUNTIME_TYPE_SHORT_NAME,
description = Constants.Options.JS_RUNTIME_TYPE_DESCRIPTION,
).default(RuntimeType.V8)
).default(Constants.Options.JS_RUNTIME_TYPE_DEFAULT_TYPE)
val module by argParser.option(
ArgType.Boolean,
shortName = Constants.Options.MODULE_SHORT_NAME,
description = Constants.Options.MODULE_DESCRIPTION,
).default(Constants.Options.MODULE_DEFAULT_VALUE)
val scriptName by argParser.option(
ArgType.String,
shortName = Constants.Options.SCRIPT_NAME_SHORT_NAME,
Expand All @@ -40,12 +45,13 @@ fun main(args: Array<String>) {
argParser.parse(args)
val options = Options(
runtimeType.value,
module,
scriptName,
)
val javetShell = JavetShell(options)
val exitCode =
try {
javetShell.run()
javetShell.execute()
} catch (t: Throwable) {
t.printStackTrace()
ExitCode.UnknownError
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@

package com.caoccao.javet.shell.constants

import com.caoccao.javet.shell.enums.RuntimeType

object Constants {
object Application {
const val AWAIT_INTERVAL_IN_MILLIS = 100L
const val NAME = "Javet Shell"
const val VERSION = "0.1.0"
}

object Options {
val JS_RUNTIME_TYPE_DEFAULT_TYPE = RuntimeType.V8
const val JS_RUNTIME_TYPE_DESCRIPTION = "JS runtime type"
const val JS_RUNTIME_TYPE_SHORT_NAME = "r"
const val MODULE_DEFAULT_VALUE = false
const val MODULE_DESCRIPTION = "Module"
const val MODULE_SHORT_NAME = "m"
const val SCRIPT_NAME_DEFAULT_VALUE = "main.js"
const val SCRIPT_NAME_DESCRIPTION = "Script name"
const val SCRIPT_NAME_SHORT_NAME = "n"
const val SCRIPT_NAME_SHORT_NAME = "s"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ import com.caoccao.javet.enums.JSRuntimeType

data class Options(
val jsRuntimeType: JSRuntimeType,
val module: Boolean,
val scriptName: String,
)

0 comments on commit 42c7a29

Please sign in to comment.