@react-native-quickjs/quickjs 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +31 -0
  4. package/README.md +217 -0
  5. package/ReactNativeQuickJS.podspec +197 -0
  6. package/android/CMakeLists.txt +134 -0
  7. package/android/build.gradle +214 -0
  8. package/android/quickjs.gradle +39 -0
  9. package/android/src/main/AndroidManifest.xml +2 -0
  10. package/android/src/main/java/com/reactnativequickjs/quickjs/QuickJSInstance.kt +39 -0
  11. package/android/src/main/java/com/reactnativequickjs/quickjs/QuickJSPackage.kt +32 -0
  12. package/android/src/main/jni/JJSRuntimeFactory.h +37 -0
  13. package/android/src/main/jni/JQuickJSInstance.cpp +27 -0
  14. package/android/src/main/jni/JQuickJSInstance.h +46 -0
  15. package/android/src/main/jni/OnLoad.cpp +15 -0
  16. package/app.plugin.js +11 -0
  17. package/apple/RCTQuickJSInstanceFactory.h +32 -0
  18. package/apple/RCTQuickJSInstanceFactory.mm +16 -0
  19. package/bin/qjsc/darwin-arm64/qjsc +0 -0
  20. package/bin/qjsc/darwin-x64/qjsc +0 -0
  21. package/bin/qjsc/linux-arm64/qjsc +0 -0
  22. package/bin/qjsc/linux-x64/qjsc +0 -0
  23. package/bin/qjsc/manifest.json +11 -0
  24. package/bin/qjsc/win32-x64/qjsc.exe +0 -0
  25. package/bin/react-native-quickjs.js +28 -0
  26. package/cmake/jsi.cmake +24 -0
  27. package/cmake/quickjs.cmake +125 -0
  28. package/engine/quickjs-rel/LICENSE +24 -0
  29. package/engine/quickjs-rel/MANIFEST.json +55 -0
  30. package/engine/quickjs-rel/builtin-array-fromasync.h +120 -0
  31. package/engine/quickjs-rel/builtin-iterator-zip-keyed.h +332 -0
  32. package/engine/quickjs-rel/builtin-iterator-zip.h +337 -0
  33. package/engine/quickjs-rel/cutils.h +1998 -0
  34. package/engine/quickjs-rel/dtoa.c +1619 -0
  35. package/engine/quickjs-rel/dtoa.h +87 -0
  36. package/engine/quickjs-rel/libregexp-opcode.h +73 -0
  37. package/engine/quickjs-rel/libregexp.c +3478 -0
  38. package/engine/quickjs-rel/libregexp.h +101 -0
  39. package/engine/quickjs-rel/libunicode-table.h +5173 -0
  40. package/engine/quickjs-rel/libunicode.c +2069 -0
  41. package/engine/quickjs-rel/libunicode.h +172 -0
  42. package/engine/quickjs-rel/list.h +107 -0
  43. package/engine/quickjs-rel/quickjs-atom.h +280 -0
  44. package/engine/quickjs-rel/quickjs-c-atomics.h +54 -0
  45. package/engine/quickjs-rel/quickjs-opcode.h +385 -0
  46. package/engine/quickjs-rel/quickjs.c +64854 -0
  47. package/engine/quickjs-rel/quickjs.h +1577 -0
  48. package/modules/cdp/quickjs-cdp.c +1386 -0
  49. package/modules/cdp/quickjs-cdp.h +122 -0
  50. package/modules/cdp/react/QuickJSInspector.cpp +322 -0
  51. package/modules/cdp/react/QuickJSInspector.h +114 -0
  52. package/modules/hermes-compat/include/hermes/DebuggerAPI.h +20 -0
  53. package/modules/hermes-compat/include/hermes/Public/CrashManager.h +47 -0
  54. package/modules/hermes-compat/include/hermes/Public/CtorConfig.h +88 -0
  55. package/modules/hermes-compat/include/hermes/Public/GCConfig.h +83 -0
  56. package/modules/hermes-compat/include/hermes/Public/HermesExport.h +17 -0
  57. package/modules/hermes-compat/include/hermes/Public/RuntimeConfig.h +66 -0
  58. package/modules/hermes-compat/include/hermes/Public/SamplingProfiler.h +22 -0
  59. package/modules/hermes-compat/include/hermes/hermes.h +195 -0
  60. package/modules/hermes-compat/include/hermes/inspector/RuntimeAdapter.h +43 -0
  61. package/modules/hermes-compat/include/hermes/inspector-modern/chrome/Registration.h +31 -0
  62. package/modules/hermes-compat/include/hermes-compat/Diagnostics.h +35 -0
  63. package/modules/hermes-compat/src/HermesCompat.cpp +557 -0
  64. package/package.json +104 -0
  65. package/scripts/bytecode/compile.js +99 -0
  66. package/scripts/expo/plugin.js +231 -0
  67. package/scripts/postinstall.js +74 -0
  68. package/scripts/react_native_quickjs_pods.rb +237 -0
  69. package/scripts/setup/edits.js +311 -0
  70. package/scripts/setup/run.js +121 -0
  71. package/src/bytecode/QuickJSBytecode.cpp +50 -0
  72. package/src/bytecode/QuickJSBytecode.h +50 -0
  73. package/src/module/QuickJSCompat.cpp +92 -0
  74. package/src/module/QuickJSCompat.h +19 -0
  75. package/src/module/QuickJSModule.cpp +70 -0
  76. package/src/module/QuickJSModule.h +108 -0
  77. package/src/module/QuickJSModuleNative.h +93 -0
  78. package/src/runtime/QuickJSInstance.cpp +37 -0
  79. package/src/runtime/QuickJSInstance.h +74 -0
  80. package/src/runtime/QuickJSRuntime.cpp +1864 -0
  81. package/src/runtime/QuickJSRuntime.h +529 -0
  82. package/src/runtime/QuickJSRuntimeConfig.h +103 -0
  83. package/src/runtime/QuickJSRuntimeFactory.cpp +34 -0
  84. package/src/runtime/QuickJSRuntimeFactory.h +24 -0
@@ -0,0 +1,214 @@
1
+ buildscript {
2
+ ext.ReactNativeQuickJS = [
3
+ kotlinVersion: "2.0.21",
4
+ minSdkVersion: 24,
5
+ compileSdkVersion: 36
6
+ ]
7
+
8
+ ext.getExtOrDefault = { prop ->
9
+ if (rootProject.ext.has(prop)) {
10
+ return rootProject.ext.get(prop)
11
+ }
12
+
13
+ return ReactNativeQuickJS[prop]
14
+ }
15
+
16
+ repositories {
17
+ google()
18
+ mavenCentral()
19
+ }
20
+
21
+ dependencies {
22
+ classpath "com.android.tools.build:gradle:8.7.2"
23
+ // noinspection DifferentKotlinGradleVersion
24
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
25
+ }
26
+ }
27
+
28
+ apply plugin: "com.android.library"
29
+ apply plugin: "kotlin-android"
30
+
31
+ android {
32
+ namespace "com.reactnativequickjs.quickjs"
33
+
34
+ // Follow the app's NDK, or let the Android plugin choose. Pinning our own
35
+ // would compile this library with a different toolchain than the app.
36
+ if (rootProject.ext.has("ndkVersion")) {
37
+ ndkVersion rootProject.ext.get("ndkVersion")
38
+ }
39
+
40
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
41
+
42
+ defaultConfig {
43
+ minSdkVersion getExtOrDefault("minSdkVersion")
44
+
45
+ externalNativeBuild {
46
+ cmake {
47
+ // ANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES gives the shared library 16 KB
48
+ // LOAD alignment. Without it we link at 4 KB while every prebuilt in
49
+ // the same APK -- libreactnative.so, libjsi.so, libfbjni.so,
50
+ // libc++_shared.so -- is already 16 KB, and on an Android 15 kernel
51
+ // the loader refuses ours outright:
52
+ //
53
+ // "...so" program alignment (4096) cannot be smaller than
54
+ // system page size (16384)
55
+ //
56
+ // The process is killed at System.loadLibrary, so there is no partial
57
+ // functionality to notice: the app does not start. NDK r27 leaves this
58
+ // off by default, r28 turns it on, and no host build can see it.
59
+ arguments "-DANDROID_STL=c++_shared",
60
+ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON",
61
+ "-DREACT_NATIVE_DIR=${reactNativeDir()}"
62
+
63
+ // Left unset, CMakeLists.txt takes the DevTools backend from the build
64
+ // type. -PrnqjsEnableCdp=true|false forces it either way.
65
+ if (project.hasProperty('rnqjsEnableCdp')) {
66
+ def on = project.property('rnqjsEnableCdp').toString() != 'false'
67
+ arguments "-DRNQJS_ENABLE_CDP=${on ? 'ON' : 'OFF'}"
68
+ }
69
+
70
+ // Ships the Hermes compatibility shim as libhermesvm.so, so libraries
71
+ // that link against Hermes -- react-native-worklets, and so
72
+ // react-native-reanimated -- run on QuickJS unmodified.
73
+ arguments "-DRNQJS_HERMES_COMPAT=${hermesCompatEnabled() ? 'ON' : 'OFF'}"
74
+
75
+ abiFilters(*reactNativeArchitectures())
76
+ }
77
+ }
78
+ }
79
+
80
+ externalNativeBuild {
81
+ cmake {
82
+ path "CMakeLists.txt"
83
+ version "3.22.1"
84
+ }
85
+ }
86
+
87
+ buildFeatures {
88
+ // Required to consume ReactAndroid::jsi and ReactAndroid::reactnative from
89
+ // the react-android AAR via find_package(ReactAndroid CONFIG).
90
+ prefab true
91
+ }
92
+
93
+ packagingOptions {
94
+ // These ship with React Native itself; a second copy would conflict at
95
+ // load time.
96
+ excludes += [
97
+ "**/libc++_shared.so",
98
+ "**/libfbjni.so",
99
+ "**/libjsi.so",
100
+ "**/libreactnative.so",
101
+ ]
102
+ }
103
+
104
+ compileOptions {
105
+ sourceCompatibility JavaVersion.VERSION_17
106
+ targetCompatibility JavaVersion.VERSION_17
107
+ }
108
+ }
109
+
110
+ // Whether to build the Hermes compatibility shim.
111
+ //
112
+ // Autolinking puts this library into every app that has the package installed,
113
+ // including one still running Hermes and one part-way through switching over.
114
+ // The shim is named libhermesvm.so, because that is the name the libraries
115
+ // needing it look for, so building it in a Hermes app puts a second file of
116
+ // that name into the merge -- and a ~100 KB shim winning over the real engine
117
+ // leaves the app dead at startup with NoClassDefFoundError: HermesInstance.
118
+ //
119
+ // So it is built only once the app has actually left Hermes, which is what
120
+ // hermesEnabled=false in gradle.properties says. -PrnqjsHermesCompat decides
121
+ // it outright either way.
122
+ def hermesCompatEnabled() {
123
+ if (project.hasProperty('rnqjsHermesCompat')) {
124
+ return project.property('rnqjsHermesCompat').toString() != 'false'
125
+ }
126
+ return rootProject.findProperty('hermesEnabled')?.toString() == 'false'
127
+ }
128
+
129
+ // Resolved through node so this works regardless of how the consuming app
130
+ // hoists its node_modules.
131
+ def reactNativeDir() {
132
+ def resolved = providers.exec {
133
+ workingDir(rootDir)
134
+ commandLine("node", "--print", "require.resolve('react-native/package.json')")
135
+ }.standardOutput.asText.get().trim()
136
+
137
+ return new File(resolved).getParentFile().getAbsolutePath()
138
+ }
139
+
140
+ def reactNativeArchitectures() {
141
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
142
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
143
+ }
144
+
145
+ dependencies {
146
+ implementation "com.facebook.react:react-android"
147
+ implementation "com.facebook.fbjni:fbjni:0.7.0"
148
+ }
149
+
150
+ // The app template picks Hermes or JavaScriptCore in its own build.gradle, and
151
+ // an app on QuickJS wants neither -- but hermesEnabled=false lands it in the
152
+ // JavaScriptCore branch. Gradle gives a library no way to drop a dependency the
153
+ // app itself declared, so warn instead.
154
+ gradle.projectsEvaluated {
155
+ rootProject.subprojects.each { app ->
156
+ if (!app.plugins.hasPlugin("com.android.application")) return
157
+
158
+ def declared = app.configurations.findByName("implementation")
159
+ ?.dependencies?.collect { it.name } ?: []
160
+
161
+ if (declared.contains("hermes-android")) {
162
+ app.logger.warn("[ReactNativeQuickJS] ${app.path} bundles Hermes. Set " +
163
+ "hermesEnabled=false in gradle.properties, or a release bundle is " +
164
+ "Hermes bytecode that QuickJS cannot execute.")
165
+ }
166
+ if (declared.any { it.startsWith("jsc-android") }) {
167
+ app.logger.warn("[ReactNativeQuickJS] ${app.path} bundles JavaScriptCore " +
168
+ "and never loads it. Remove the jscFlavor dependency to save about " +
169
+ "10 MB per architecture.")
170
+ }
171
+ }
172
+ }
173
+
174
+ // Compile the release bundle to QuickJS bytecode, after React Native has
175
+ // written it. Debug builds load JavaScript from Metro and never produce a
176
+ // bundle, so there is nothing to compile. -PrnqjsBytecode=false turns it off.
177
+
178
+ // ExecOperations is how a Gradle 9 build spawns a process; project.exec was
179
+ // removed. A plain ProcessBuilder also runs, but not identically: under a
180
+ // Volta-managed node it fails to resolve a version at all, in a build where
181
+ // React Native's own bundle task -- which goes through ExecOperations -- had
182
+ // just run the same binary.
183
+ interface ReactNativeQuickJSProcess {
184
+ @javax.inject.Inject
185
+ org.gradle.process.ExecOperations getExecOperations()
186
+ }
187
+
188
+ gradle.projectsEvaluated {
189
+ if (project.findProperty('rnqjsBytecode')?.toString() == 'false') return
190
+
191
+ def compiler = file("${projectDir}/../scripts/bytecode/compile.js")
192
+
193
+ rootProject.subprojects.each { app ->
194
+ if (!app.plugins.hasPlugin("com.android.application")) return
195
+
196
+ def process = app.objects.newInstance(ReactNativeQuickJSProcess).execOperations
197
+ // The same node React Native bundles with, including an override of it.
198
+ def node = app.extensions.findByName('react')?.nodeExecutableAndArgs?.getOrNull() ?: ['node']
199
+
200
+ app.tasks.matching { it.name ==~ /createBundle.*JsAndAssets/ }.configureEach { bundleTask ->
201
+ bundleTask.doLast {
202
+ // Found by name rather than by reading the task's own properties,
203
+ // which are React Native Gradle plugin internals.
204
+ def assets = app.layout.buildDirectory.dir("generated/assets").get().asFile
205
+ app.fileTree(assets).matching { include '**/index.android.bundle' }.each { bundle ->
206
+ process.exec {
207
+ commandLine(*node, compiler.absolutePath, bundle.absolutePath)
208
+ workingDir app.rootDir
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
@@ -0,0 +1,39 @@
1
+ // Copyright (c) Ammar Ahmed.
2
+ //
3
+ // This source code is licensed under the MIT license found in the
4
+ // LICENSE file in the root directory of this source tree.
5
+ //
6
+ // Applied from the app's android/app/build.gradle:
7
+ //
8
+ // apply from: file("../../node_modules/@react-native-quickjs/quickjs/android/quickjs.gradle")
9
+ //
10
+ // React Native strips the JavaScript engine the app is not using. It knows two
11
+ // engines, so "not Hermes" means "delete **/libhermesvm.so" -- and that is the
12
+ // name the Hermes compatibility shim has to carry, because it is what
13
+ // react-native-worklets records as NEEDED. See useThirdPartyJSC in
14
+ // NdkConfiguratorUtils.kt.
15
+ //
16
+ // Turning that cleanup off would also stop JavaScriptCore and the Hermes
17
+ // tooling library being stripped, so it is replaced here rather than dropped:
18
+ // the same removals, minus the one file this engine needs.
19
+
20
+ react {
21
+ enableSoCleanup = false
22
+ }
23
+
24
+ androidComponents {
25
+ onVariants(selector().all()) { variant ->
26
+ variant.packaging.jniLibs.excludes.addAll([
27
+ "**/libjsc.so",
28
+ "**/libjsctooling.so",
29
+ "**/libhermestooling.so",
30
+ ])
31
+ }
32
+ }
33
+
34
+ // A transitively pulled Hermes would put a second libhermesvm.so into the merge
35
+ // and the winner would be whichever the merger saw first -- a real engine,
36
+ // satisfying worklets and starting up silently. So it cannot enter the graph.
37
+ configurations.configureEach {
38
+ exclude group: "com.facebook.hermes", module: "hermes-android"
39
+ }
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.reactnativequickjs.quickjs
9
+
10
+ import com.facebook.jni.HybridData
11
+ import com.facebook.jni.annotations.DoNotStrip
12
+ import com.facebook.react.runtime.JSRuntimeFactory
13
+ import com.facebook.soloader.SoLoader
14
+
15
+ /**
16
+ * The QuickJS engine, as a drop-in replacement for
17
+ * `com.facebook.react.runtime.hermes.HermesInstance`.
18
+ *
19
+ * Pass it to `DefaultReactHost.getDefaultReactHost(...)` in your
20
+ * `MainApplication`:
21
+ * ```
22
+ * override val reactHost: ReactHost
23
+ * get() = getDefaultReactHost(
24
+ * applicationContext,
25
+ * reactNativeHost,
26
+ * jsRuntimeFactory = QuickJSInstance(),
27
+ * )
28
+ * ```
29
+ */
30
+ public class QuickJSInstance : JSRuntimeFactory(initHybrid()) {
31
+
32
+ public companion object {
33
+ @JvmStatic @DoNotStrip protected external fun initHybrid(): HybridData
34
+
35
+ init {
36
+ SoLoader.loadLibrary("quickjsinstancejni")
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.reactnativequickjs.quickjs
9
+
10
+ import com.facebook.react.ReactPackage
11
+ import com.facebook.react.bridge.NativeModule
12
+ import com.facebook.react.bridge.ReactApplicationContext
13
+ import com.facebook.react.uimanager.ViewManager
14
+
15
+ /**
16
+ * Deliberately empty.
17
+ *
18
+ * This package exports no modules and no view managers -- QuickJS is wired in
19
+ * through [QuickJSInstance], not through the module system. It exists only
20
+ * because React Native's autolinking skips any Android library that does not
21
+ * expose a ReactPackage (see cli-config-android dependencyConfig), and without
22
+ * autolinking the gradle project is never included in the app build.
23
+ */
24
+ public class QuickJSPackage : ReactPackage {
25
+ override fun createNativeModules(
26
+ reactContext: ReactApplicationContext
27
+ ): List<NativeModule> = emptyList()
28
+
29
+ override fun createViewManagers(
30
+ reactContext: ReactApplicationContext
31
+ ): List<ViewManager<*, *>> = emptyList()
32
+ }
@@ -0,0 +1,37 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * ---------------------------------------------------------------------------
8
+ * Verbatim copy of
9
+ * ReactAndroid/src/main/jni/react/runtime/jni/JJSRuntimeFactory.h
10
+ *
11
+ * React Native exports only ReactCommon/jsitooling through its prefab headers,
12
+ * so an out-of-tree engine has to carry its own copy of this one. It is a pure
13
+ * declaration -- it binds to the com.facebook.react.runtime.JSRuntimeFactory
14
+ * class that ships in the app -- so the copy duplicates no code, only a version
15
+ * coupling. Re-check it when raising the supported React Native version.
16
+ * ---------------------------------------------------------------------------
17
+ */
18
+
19
+ #pragma once
20
+
21
+ #include <fbjni/fbjni.h>
22
+ #include <jni.h>
23
+ #include <react/runtime/JSRuntimeFactory.h>
24
+
25
+ namespace facebook::react {
26
+
27
+ class JJSRuntimeFactory : public jni::HybridClass<JJSRuntimeFactory>,
28
+ public JSRuntimeFactory {
29
+ public:
30
+ static auto constexpr kJavaDescriptor =
31
+ "Lcom/facebook/react/runtime/JSRuntimeFactory;";
32
+
33
+ private:
34
+ friend HybridBase;
35
+ };
36
+
37
+ } // namespace facebook::react
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include "JQuickJSInstance.h"
9
+
10
+ namespace facebook::react {
11
+
12
+ jni::local_ref<JQuickJSInstance::jhybriddata> JQuickJSInstance::initHybrid(
13
+ jni::alias_ref<jclass>) {
14
+ return makeCxxInstance();
15
+ }
16
+
17
+ std::unique_ptr<JSRuntime> JQuickJSInstance::createJSRuntime(
18
+ std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
19
+ return instance_.createJSRuntime(std::move(msgQueueThread));
20
+ }
21
+
22
+ void JQuickJSInstance::registerNatives() {
23
+ registerHybrid(
24
+ {makeNativeMethod("initHybrid", JQuickJSInstance::initHybrid)});
25
+ }
26
+
27
+ } // namespace facebook::react
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include <react/runtime/JSRuntimeFactory.h>
12
+
13
+ #include <memory>
14
+
15
+ #include "JJSRuntimeFactory.h"
16
+ #include "QuickJSInstance.h"
17
+
18
+ namespace facebook::react {
19
+
20
+ class MessageQueueThread;
21
+
22
+ /**
23
+ * The fbjni hybrid behind the Kotlin QuickJSInstance, mirroring React Native's
24
+ * own JHermesInstance: the Java-side object is a JSRuntimeFactory and the C++
25
+ * side answers createJSRuntime().
26
+ */
27
+ class JQuickJSInstance
28
+ : public jni::HybridClass<JQuickJSInstance, JJSRuntimeFactory> {
29
+ public:
30
+ static constexpr auto kJavaDescriptor =
31
+ "Lcom/reactnativequickjs/quickjs/QuickJSInstance;";
32
+
33
+ static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
34
+
35
+ static void registerNatives();
36
+
37
+ std::unique_ptr<JSRuntime> createJSRuntime(
38
+ std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept;
39
+
40
+ private:
41
+ friend HybridBase;
42
+
43
+ QuickJSInstance instance_;
44
+ };
45
+
46
+ } // namespace facebook::react
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #include <fbjni/fbjni.h>
9
+
10
+ #include "JQuickJSInstance.h"
11
+
12
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
13
+ return facebook::jni::initialize(
14
+ vm, [] { facebook::react::JQuickJSInstance::registerNatives(); });
15
+ }
package/app.plugin.js ADDED
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * Expo resolves a plugin referenced by package name to app.plugin.js at the
8
+ * package root.
9
+ */
10
+
11
+ module.exports = require('./scripts/expo/plugin.js');
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import <react/runtime/JSRuntimeFactoryCAPI.h>
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ /**
15
+ * Creates the QuickJS engine factory, as a drop-in replacement for
16
+ * `jsrt_create_hermes_factory()`.
17
+ *
18
+ * Override `createJSRuntimeFactory` on your React Native factory delegate:
19
+ *
20
+ * - (JSRuntimeFactoryRef)createJSRuntimeFactory
21
+ * {
22
+ * return jsrt_create_quickjs_factory();
23
+ * }
24
+ *
25
+ * Ownership of the returned factory transfers to React Native, which releases
26
+ * it with `js_runtime_factory_destroy`.
27
+ */
28
+ JSRuntimeFactoryRef jsrt_create_quickjs_factory(void);
29
+
30
+ #ifdef __cplusplus
31
+ }
32
+ #endif
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright (c) Ammar Ahmed.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ #import "RCTQuickJSInstanceFactory.h"
9
+
10
+ #import "QuickJSInstance.h"
11
+
12
+ using namespace facebook::react;
13
+
14
+ JSRuntimeFactoryRef jsrt_create_quickjs_factory(void) {
15
+ return reinterpret_cast<JSRuntimeFactoryRef>(new QuickJSInstance());
16
+ }
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,11 @@
1
+ {
2
+ "_comment": "Generated by .github/workflows/bytecode-compilers.yml. Do not edit.",
3
+ "bcVersion": 28,
4
+ "platforms": [
5
+ "darwin-arm64",
6
+ "darwin-x64",
7
+ "linux-arm64",
8
+ "linux-x64",
9
+ "win32-x64"
10
+ ]
11
+ }
Binary file
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Copyright (c) Ammar Ahmed.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const run = require('../scripts/setup/run.js');
12
+ const [command, ...argv] = process.argv.slice(2);
13
+
14
+ if (command in run) {
15
+ process.exit(run[command](argv));
16
+ }
17
+
18
+ console.log(`
19
+ react-native-quickjs
20
+
21
+ install configure this app to run on QuickJS
22
+ revert configure it back to Hermes
23
+ doctor report which parts are configured
24
+
25
+ --project <path> act on this app instead of the current directory
26
+ --dry-run show what would change, write nothing
27
+ `);
28
+ process.exit(command === undefined || command === '--help' || command === '-h' ? 0 : 1);
@@ -0,0 +1,24 @@
1
+ # Copyright (c) Ammar Ahmed.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory of this source tree.
5
+ #
6
+ # Defines the `jsi` static library.
7
+ #
8
+ # It compiles React Native's own copy of JSI, not a vendored one. jsi::Runtime
9
+ # is abstract, so building against different headers than the app links is a
10
+ # vtable mismatch: it compiles, links, and crashes at the first virtual call.
11
+
12
+ set(REACT_NATIVE_DIR "${CMAKE_CURRENT_LIST_DIR}/../node_modules/react-native"
13
+ CACHE PATH "Path to the react-native package")
14
+ set(JSI_DIR "${REACT_NATIVE_DIR}/ReactCommon/jsi")
15
+
16
+ if(NOT EXISTS "${JSI_DIR}/jsi/jsi.cpp")
17
+ message(FATAL_ERROR
18
+ "Could not find JSI at ${JSI_DIR}.\n"
19
+ "Run `npm install` first, or pass -DREACT_NATIVE_DIR=/path/to/react-native")
20
+ endif()
21
+
22
+ add_library(jsi STATIC "${JSI_DIR}/jsi/jsi.cpp")
23
+ target_include_directories(jsi PUBLIC "${JSI_DIR}")
24
+ set_target_properties(jsi PROPERTIES POSITION_INDEPENDENT_CODE ON)