Skip to content

Commit

Permalink
feat(graalvm): synthetic modules
Browse files Browse the repository at this point in the history
feat(graalvm-js): add new `graalvm-js` module for graaljs integration
feat(graalvm-js): initial structure and api for elide's import router
feat(graalvm-ts): move js realm patcher to `graalvm-js` module
feat(graalvm): initialize javascript when plugin is added
chore: reintroduce graalvm/graaljs modules and pins

Signed-off-by: Sam Gammon <sam@elide.dev>
  • Loading branch information
sgammon committed Feb 23, 2025
1 parent c00e776 commit c5b9974
Show file tree
Hide file tree
Showing 17 changed files with 178 additions and 10 deletions.
10 changes: 9 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,12 @@
path = third_party/madler/zlib
url = git@github.com:madler/zlib.git
ignore = dirty

shallow = true
[submodule "graalvm"]
path = third_party/oracle/graalvm/graal
url = git@github.com:oracle/graal.git
shallow = true
[submodule "graaljs"]
path = third_party/oracle/graalvm/graaljs
url = git@github.com:elide-dev/graaljs.git
shallow = true
12 changes: 12 additions & 0 deletions packages/cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -1963,3 +1963,15 @@ listOf(
}
}
}

val (jsGroup, jsName) = libs.graalvm.js.language.get().let {
it.group to it.name
}
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("${jsGroup}:${jsName}")).apply {
using(project(":packages:graalvm-js"))
because("Uses Elide's patched version of GraalJs")
}
}
}
5 changes: 5 additions & 0 deletions packages/graalvm-js/api/graalvm-js.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class elide/runtime/lang/javascript/JSRealmPatcher {
public fun <init> ()V
public static fun setModuleLoader (Lcom/oracle/truffle/js/runtime/JSRealm;Lcom/oracle/truffle/js/runtime/objects/JSModuleLoader;)V
}

64 changes: 64 additions & 0 deletions packages/graalvm-js/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

import elide.internal.conventions.kotlin.KotlinTarget
import elide.internal.conventions.publishing.publish

plugins {
alias(libs.plugins.micronaut.graalvm)

kotlin("jvm")
kotlin("kapt")
kotlin("plugin.allopen")

alias(libs.plugins.elide.conventions)
}

elide {
publishing {
id = "graalvm-js"
name = "Elide JS integration package for GraalVM"
description = "Integration package with GraalVM, Elide, and JS."

publish("jvm") {
from(components["kotlin"])
}
}

kotlin {
target = KotlinTarget.JVM
explicitApi = true
}
}

val gvmJarsRoot = rootProject.layout.projectDirectory.dir("third_party/oracle")

val patchedLibs = files(
gvmJarsRoot.file("graaljs.jar"),
)

val patchedDependencies: Configuration by configurations.creating {
isCanBeResolved = true
}

dependencies {
api(projects.packages.engine)
api(patchedLibs)
patchedDependencies(patchedLibs)
}

configurations.all {
libs.graalvm.js.language.get().let {
exclude(group = it.group, module = it.name)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
* Copyright (c) 2024-2025 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
Expand All @@ -10,18 +10,19 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/
package elide.runtime.lang.typescript;
package elide.runtime.lang.javascript;

import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.objects.JSModuleLoader;
import java.lang.reflect.Field;

class JSRealmPatcher {
public static void setTSModuleLoader(JSRealm jsRealm, TypeScriptModuleLoader newModuleLoader) {
public class JSRealmPatcher {
public static void setModuleLoader(JSRealm jsRealm, JSModuleLoader newModuleLoader) {
try {
Field moduleLoaderField = JSRealm.class.getDeclaredField("moduleLoader");
moduleLoaderField.setAccessible(true);
Object moduleLoader = moduleLoaderField.get(jsRealm);
if (!(moduleLoader instanceof TypeScriptModuleLoader)) {
if (moduleLoader != newModuleLoader) {
moduleLoaderField.set(jsRealm, newModuleLoader);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package elide.runtime.lang.javascript

import com.oracle.truffle.js.runtime.JSEngine
import com.oracle.truffle.js.runtime.JSModuleLoaderFactory
import com.oracle.truffle.js.runtime.JSRealm
import com.oracle.truffle.js.runtime.objects.JSModuleLoader
import java.util.*
import kotlinx.atomicfu.atomic

/**
* ## Elide JavaScript Module Router
*/
public object ElideJsModuleRouter : JSModuleLoaderFactory {
private val initialized = atomic(false)

@JvmStatic public fun install() {
if (!initialized.getAndSet(true)) {
JSEngine.setModuleLoaderFactory(this)
}
}

override fun createLoader(realm: JSRealm, defaultFactory: JSModuleLoaderFactory): Optional<JSModuleLoader> = defaultFactory.createLoader(realm, defaultFactory)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package elide.runtime.lang.javascript

import kotlinx.atomicfu.atomic

/**
* ## JavaScript Language Utilities
*
* Static utilities for internal engine use.
*/
public object JavaScriptLang {
private val initialized = atomic(false)

public fun initialize() {
if (initialized.compareAndSet(expect = false, update = true)) {
ElideJsModuleRouter.install()
}
}
}
17 changes: 17 additions & 0 deletions packages/graalvm-ts/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ elide {
dependencies {
kapt(libs.graalvm.truffle.processor)
api(projects.packages.engine)
api(projects.packages.graalvmJs)
api(libs.graalvm.truffle.api)
implementation(libs.commons.io)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.graalvm.js.language)
implementation(libs.graalvm.shadowed.icu4j)
implementation(libs.graalvm.regex)

// Testing
testImplementation(projects.packages.test)
Expand All @@ -71,3 +75,16 @@ tasks {
systemProperty("elide.test", "true")
}
}

val (jsGroup, jsName) = libs.graalvm.js.language.get()
.let {
it.group to it.name
}
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("$jsGroup:$jsName")).apply {
using(project(":packages:graalvm-js"))
because("Uses Elide's patched version of GraalJs")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
* Copyright (c) 2024-2025 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
Expand All @@ -23,6 +23,7 @@
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.runtime.JSEngine;
import com.oracle.truffle.js.runtime.JSRealm;
import elide.runtime.lang.javascript.JSRealmPatcher;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.graalvm.polyglot.SandboxPolicy;
Expand Down Expand Up @@ -84,7 +85,7 @@ protected JSRealm createContext(Env currentEnv) {
}
var ctx = JSEngine.createJSContext(js, jsEnv);
var realm = ctx.createRealm(jsEnv);
JSRealmPatcher.setTSModuleLoader(realm, new TypeScriptModuleLoader(realm, tsCompiler));
JSRealmPatcher.setModuleLoader(realm, new TypeScriptModuleLoader(realm, tsCompiler));
return realm;
}

Expand Down Expand Up @@ -118,7 +119,7 @@ protected TSRootNode(TruffleLanguage<?> language, RootNode delegate) {
@TruffleBoundary
private void setModuleLoader() {
JSRealm realm = JSRealm.get(delegate);
JSRealmPatcher.setTSModuleLoader(realm, new TypeScriptModuleLoader(realm, tsCompiler));
JSRealmPatcher.setModuleLoader(realm, new TypeScriptModuleLoader(realm, tsCompiler));
}

@Override
Expand Down
12 changes: 12 additions & 0 deletions packages/graalvm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -669,3 +669,15 @@ if (enableBenchmarks) afterEvaluate {
}.toString())
}
}

val (jsGroup, jsName) = libs.graalvm.js.language.get().let {
it.group to it.name
}
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("${jsGroup}:${jsName}")).apply {
using(project(":packages:graalvm-js"))
because("Uses Elide's patched version of GraalJs")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package elide.runtime.plugins.js

import com.oracle.truffle.js.runtime.JSContextOptions
import org.graalvm.polyglot.Engine
import org.graalvm.polyglot.Source
import java.util.concurrent.atomic.AtomicBoolean
Expand All @@ -27,6 +28,7 @@ import elide.runtime.core.extensions.disableOptions
import elide.runtime.core.extensions.enableOptions
import elide.runtime.core.extensions.setOptions
import elide.runtime.core.plugin
import elide.runtime.lang.javascript.JavaScriptLang
import elide.runtime.plugins.AbstractLanguagePlugin
import elide.runtime.plugins.AbstractLanguagePlugin.LanguagePluginManifest
import elide.runtime.plugins.env.Environment
Expand Down Expand Up @@ -156,6 +158,7 @@ import elide.runtime.plugins.js.JavaScriptVersion.*
"js.unhandled-rejections" to UNHANDLED_REJECTIONS,
// Experimental:
"js.charset" to config.charset.name(),
"js.module-loader-factory" to JSContextOptions.ModuleLoaderFactoryMode.HANDLER.toString(),
)

setOptions(
Expand Down Expand Up @@ -207,6 +210,7 @@ import elide.runtime.plugins.js.JavaScriptVersion.*
override val key: Key<JavaScript> = Key(JS_PLUGIN_ID)

override fun install(scope: InstallationScope, configuration: JavaScriptConfig.() -> Unit): JavaScript {
JavaScriptLang.initialize()
configureLanguageSupport(scope)

// resolve the env plugin (if present, otherwise ignore silently)
Expand Down
2 changes: 1 addition & 1 deletion runtime
Submodule runtime updated 0 files
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ include(
":packages:graalvm",
":packages:graalvm-java",
":packages:graalvm-jvm",
":packages:graalvm-js",
":packages:graalvm-kt",
":packages:graalvm-llvm",
":packages:graalvm-py",
Expand Down
Binary file added third_party/oracle/graaljs.jar
Binary file not shown.
1 change: 1 addition & 0 deletions third_party/oracle/graalvm/graal
Submodule graal added at 804dab
1 change: 1 addition & 0 deletions third_party/oracle/graalvm/graaljs
Submodule graaljs added at e67c95
Binary file added third_party/oracle/truffle-js-snapshot-tool.jar
Binary file not shown.

0 comments on commit c5b9974

Please sign in to comment.