Skip to content

Commit 7097c3e

Browse files
committed
feat: add support for queueMicrotask
Signed-off-by: Sam Gammon <[email protected]>
1 parent ab3eccc commit 7097c3e

File tree

4 files changed

+94
-3
lines changed

4 files changed

+94
-3
lines changed

packages/graalvm/api/graalvm.api

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,14 @@ public final class elide/runtime/gvm/internals/intrinsics/ElideIntrinsicKt {
517517
public static final fun installElideBuiltin (Ljava/lang/String;Ljava/lang/Object;)V
518518
}
519519

520+
public abstract class elide/runtime/gvm/internals/intrinsics/js/AbstractJsIntrinsic : elide/runtime/intrinsics/GuestIntrinsic {
521+
public fun <init> ()V
522+
public fun displayName ()Ljava/lang/String;
523+
public fun language ()Lelide/runtime/gvm/GuestLanguage;
524+
public fun symbolicName ()Ljava/lang/String;
525+
public fun toString ()Ljava/lang/String;
526+
}
527+
520528
public synthetic class elide/runtime/gvm/internals/intrinsics/js/abort/$AbortControllerIntrinsic$Definition : io/micronaut/context/AbstractInitializableBeanDefinitionAndReference {
521529
public static final field $ANNOTATION_METADATA Lio/micronaut/core/annotation/AnnotationMetadata;
522530
public fun <init> ()V
@@ -5771,6 +5779,29 @@ public abstract interface class elide/runtime/intrinsics/testing/TestingAPI$Test
57715779
public abstract interface class elide/runtime/intrinsics/testing/TestingAPI$TestGraphNode$Test : elide/runtime/intrinsics/testing/TestingAPI$TestGraphNode {
57725780
}
57735781

5782+
public synthetic class elide/runtime/node/$QueueMicrotaskCallable$Definition : io/micronaut/context/AbstractInitializableBeanDefinitionAndReference {
5783+
public static final field $ANNOTATION_METADATA Lio/micronaut/core/annotation/AnnotationMetadata;
5784+
public fun <init> ()V
5785+
protected fun <init> (Ljava/lang/Class;Lio/micronaut/context/AbstractInitializableBeanDefinition$MethodOrFieldReference;)V
5786+
public fun instantiate (Lio/micronaut/context/BeanResolutionContext;Lio/micronaut/context/BeanContext;)Ljava/lang/Object;
5787+
public fun isEnabled (Lio/micronaut/context/BeanContext;)Z
5788+
public fun isEnabled (Lio/micronaut/context/BeanContext;Lio/micronaut/context/BeanResolutionContext;)Z
5789+
public fun load ()Lio/micronaut/inject/BeanDefinition;
5790+
}
5791+
5792+
public final synthetic class elide/runtime/node/$QueueMicrotaskCallable$Introspection : io/micronaut/inject/beans/AbstractInitializableBeanIntrospectionAndReference {
5793+
public static final field $ANNOTATION_METADATA Lio/micronaut/core/annotation/AnnotationMetadata;
5794+
public fun <init> ()V
5795+
public fun hasBuilder ()Z
5796+
public fun isBuildable ()Z
5797+
}
5798+
5799+
public final class elide/runtime/node/QueueMicrotaskCallable : elide/runtime/gvm/internals/intrinsics/js/AbstractJsIntrinsic, org/graalvm/polyglot/proxy/ProxyExecutable {
5800+
public fun <init> (Lelide/runtime/exec/GuestExecutorProvider;)V
5801+
public fun execute ([Lorg/graalvm/polyglot/Value;)Ljava/lang/Object;
5802+
public fun install (Lelide/runtime/intrinsics/GuestIntrinsic$MutableIntrinsicBindings;)V
5803+
}
5804+
57745805
public synthetic class elide/runtime/node/asserts/$NodeAssertModule$Definition : io/micronaut/context/AbstractInitializableBeanDefinitionAndReference {
57755806
public static final field $ANNOTATION_METADATA Lio/micronaut/core/annotation/AnnotationMetadata;
57765807
public fun <init> ()V

packages/graalvm/src/main/kotlin/elide/runtime/gvm/internals/intrinsics/js/AbstractJsIntrinsic.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import elide.runtime.gvm.GraalVMGuest
1717
import elide.runtime.intrinsics.GuestIntrinsic
1818

1919
/** Abstract base class for all intrinsic implementations. */
20-
internal abstract class AbstractJsIntrinsic : GuestIntrinsic {
20+
public abstract class AbstractJsIntrinsic : GuestIntrinsic {
2121
override fun language(): GuestLanguage = GraalVMGuest.JAVASCRIPT
2222
override fun symbolicName(): String = "native code"
2323
@Deprecated("Use symbolicName instead", ReplaceWith("symbolicName"))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2024-2025 Elide Technologies, Inc.
3+
*
4+
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
5+
* with the License. You may obtain a copy of the License at
6+
*
7+
* https://opensource.org/license/mit/
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
* License for the specific language governing permissions and limitations under the License.
12+
*/
13+
@file:OptIn(DelicateElideApi::class)
14+
15+
package elide.runtime.node
16+
17+
import org.graalvm.polyglot.Value
18+
import org.graalvm.polyglot.proxy.ProxyExecutable
19+
import elide.annotations.Inject
20+
import elide.annotations.Singleton
21+
import elide.runtime.core.DelicateElideApi
22+
import elide.runtime.exec.GuestExecutorProvider
23+
import elide.runtime.gvm.api.Intrinsic
24+
import elide.runtime.gvm.internals.intrinsics.js.AbstractJsIntrinsic
25+
import elide.runtime.gvm.js.JsError
26+
import elide.runtime.gvm.js.JsSymbol.JsSymbols.asPublicJsSymbol
27+
import elide.runtime.gvm.js.undefined
28+
import elide.runtime.intrinsics.GuestIntrinsic
29+
30+
// Name of the `queueMicrotask` function in the global scope.
31+
private const val QUEUE_MICROTASK_NAME = "queueMicrotask"
32+
33+
// Public JavaScript symbol for the `queueMicrotask` function.
34+
private val QUEUE_MICROTASK_SYMBOL = QUEUE_MICROTASK_NAME.asPublicJsSymbol()
35+
36+
/**
37+
* ## Queue Microtask Callable
38+
*
39+
* Mounts a callable intrinsic function at the name `queueMicrotask`, in compliance with Web JavaScript standards which
40+
* expect this function to be available in the global scope. The `queueMicrotask` function is used to queue a chunk of
41+
* code to execute safely on the JavaScript event loop.
42+
*
43+
* [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/queueMicrotask)
44+
*/
45+
@Singleton
46+
@Intrinsic(QUEUE_MICROTASK_NAME) public class QueueMicrotaskCallable @Inject constructor (
47+
private val executorProvider: GuestExecutorProvider,
48+
) : ProxyExecutable, AbstractJsIntrinsic() {
49+
override fun install(bindings: GuestIntrinsic.MutableIntrinsicBindings) {
50+
bindings[QUEUE_MICROTASK_SYMBOL] = this
51+
}
52+
53+
override fun execute(vararg arguments: Value?): Any? {
54+
val first = arguments.firstOrNull() ?: throw JsError.typeError("First argument to `queueMicrotask` is required")
55+
if (!first.canExecute()) throw JsError.typeError("First argument to `queueMicrotask` must be a function")
56+
executorProvider.executor().execute {
57+
first.execute()
58+
}
59+
return undefined()
60+
}
61+
}

packages/graalvm/src/test/kotlin/elide/runtime/intrinsics/js/JsGlobalsTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ private const val ENABLE_SUPPRESSIONS = true
5959
"isNaN",
6060
"parseFloat",
6161
"parseInt",
62+
"queueMicrotask",
6263
"decodeURI",
6364
"decodeURIComponent",
6465
"encodeURI",
@@ -158,7 +159,6 @@ private const val ENABLE_SUPPRESSIONS = true
158159
"PerformanceObserverEntryList",
159160
"performance",
160161
"process",
161-
"queueMicrotask",
162162
"ReadableByteStreamController",
163163
"ReadableStream",
164164
"ReadableStreamBYOBReader",
@@ -214,7 +214,6 @@ private const val ENABLE_SUPPRESSIONS = true
214214
"navigator", // not yet implemented
215215
"setImmediate", // not yet implemented
216216
"clearImmediate", // not yet implemented
217-
"queueMicrotask", // not yet implemented
218217
"structuredClone", // not yet implemented
219218
"InternalError", // web-standard only, not present in non-browser runtimes
220219
"BroadcastChannel", // not yet implemented

0 commit comments

Comments
 (0)