Android Bindings for QuickJS, A fine little javascript engine.

Overview

quickjs-android

Download

quickjs-androidQuickJS JavaScript 引擎的 Android 接口框架,整体基于面向对象设计,提供了自动GC功能,使用简单。armeabi-v7a 的大小仅 350KB,是 Google V8 不错的替代品,启动速度比 V8 快,内存占用更低,支持 ES2020

  • armeabi-v7a 平台下,整体占用apk空间仅 350KB;
  • JS对象自动GC,无需手动释放;
  • 支持 ES6 Module,可以使用 import、export 函数;
  • 支持 Node.js 的 CommonJS 规范,可以使用 require、exports 函数;
  • 支持绑定 Java 注解函数;
  • 支持通过 Java Function Callback 函数注册JS函数;
  • 内置 Event Queue,开发者可以在任意线程执行代码,无需关心JS单线程问题;

使用教程

引入依赖
implementation 'io.github.taoweiji.quickjs:quickjs-android:1.+'
简单示例
QuickJS quickJS = QuickJS.createRuntime();
JSContext context = quickJS.createContext();
int result = context.executeIntegerScript("var a = 2+10;\n a;", "file.js");
context.close();
quickJS.close();

对象介绍

QuickJS

运行环境,可以创建多个运行时环境,不同的环境之间不能共享对象,不使用的时候需要销毁。

QuickJS quickJS = QuickJS.createRuntime();
JSContext

由 QuickJS 创建,一个 QuickJS 可以创建多个 JSContext,不使用的时候需要销毁。

JSContext context = quickJS.createContext();
int result = context.executeIntegerScript("var a = 2+10;\n a;", "file.js");
String result = context.executeStringScript("'Hello World';", "file.js");
context.close();
JSObject
JSObject user = new JSObject(context).set("name", "Wiki").set("age", 18).set("time",System.currentTimeMillis());
Log.e("QuickJS", String.valueOf(user.getString("name")));
Log.e("QuickJS", String.valueOf(user.getInteger("age")));
Log.e("QuickJS", String.valueOf(user.getDouble("time")));

user.registerJavaMethod(new JavaVoidCallback() {
    @Override
    public void invoke(JSObject receiver, JSArray args) {
        Log.e("QuickJS", args.getString(0));
    }
}, "log");
user.executeVoidFunction("log", new JSArray(context).push("Hello World"));
JSArray
JSArray array = new JSArray(context).push(1).push(3.14).push(true).push("Hello World");
Log.e("QuickJS", String.valueOf(array.getInteger(0)));
Log.e("QuickJS", String.valueOf(array.getDouble(1)));
JSFunction
JSFunction log = new JSFunction(context, new JavaVoidCallback() {
    @Override
    public void invoke(JSObject receiver, JSArray args) {
        Log.e("QuickJS", args.getString(0));
    }
});
JSFunction message = new JSFunction(context, new JavaCallback() {
    @Override
    public Object invoke(JSObject receiver, JSArray array) {
        return "Hello World";
    }
});
context.set("console", new JSObject(context).set("log", log).set("message", message));
context.executeVoidScript("console.log(console.message())", null);
addJavascriptInterface
public class Console {
    int count = 0;

    @JavascriptInterface
    public void log(String msg) {
        count++;
        Log.d("console", msg);
    }

    @JavascriptInterface
    public void info(String msg) {
        count++;
        Log.i("console", msg);
    }

    @JavascriptInterface
    public void error(String msg) {
        count++;
        Log.e("console", msg);
    }

    @JavascriptInterface
    public int count() {
        return count;
    }
}

context.addJavascriptInterface(new Console(), "console");
context.executeVoidScript("console.log('Hello World')", null);
int count = context.executeIntegerScript("console.count()", null);
Log.d("console", String.valueOf(count));

QuickJS

方法 说明
static QuickJS createRuntime() 创建运行时
JSContext createContext() 创建上下文
void close() 销毁引擎

JSValue

对象会自动回收,开发者无需手动close()

方法 说明
static JSObject Undefined(JSContext context) 获取Undefined对象
static JSValue NULL() 获取NULL对象
TYPE getType() 获取数据类型
boolean isUndefined()

JSObject

继承JSValue

方法 说明
set(key, value) 设置属性,支持int、boolean、double、String、JSValue
int getInteger(String key) 返回值int对象值,如果没有就会返回0
boolean getBoolean(String key) 返回值boolean对象值,如果没有就会返回false
double getDouble(String key) 返回值double对象值,如果没有就会返回0
String getString(String key) 返回值String对象值,如果没有就会返回null
JSArray getArray(String key) 返回值JSArray对象值,如果没有就会返回null
JSObject getObject(String key) 可能会返回JSObject、JSArray、JSFunction,如果没有就会返回null
registerJavaMethod(JavaCallback callback, String jsFunctionName) 注册JS函数,调用函数会执行java的Callback,带有返回值
registerJavaMethod(JavaVoidCallback callback, String jsFunctionName) 注册JS函数,调用函数会执行java的Callback,不带返回值
Object executeFunction(String name, JSArray parameters) 可能会返回Integer、Double、Boolean、String、JSArray、JSObject、JSFunction、null
double executeDoubleFunction(String name, JSArray parameters) 返回 double,默认返回 0
boolean executeBooleanFunction(String name, JSArray parameters) 返回boolean,默认人会false
String executeStringFunction(String name, JSArray parameters) 返回String,默认返回null
JSArray executeArrayFunction(String name, JSArray parameters) 返回JSArray,默认返回null
JSObject executeObjectFunction(String name, JSArray parameters) 可能会返回JSObject、JSArray、JSFunction,默认返回null
void executeVoidFunction(String name, JSArray parameters) 没有返回值
Object executeFunction2(String name, Object... parameters) 可能返回Integer、Double、Boolean、String、JSArray、JSObject、JSFunction、null,入参为java数组,仅支持Integer、Double、Boolean、String、JSArray、JSObject、JSFunction、null
boolean contains(String key) 是否包含该字段
String[] getKeys() 获取属性列表

JSArray

继承JSObject

方法 说明
push(value) 设置属性,支持int、boolean、double、String、JSValue
int getInteger(String key) 返回值int对象值,如果没有就会返回0
boolean getBoolean(String key) 返回值boolean对象值,如果没有就会返回false
double getDouble(String key) 返回值double对象值,如果没有就会返回0
String getString(String key) 返回值String对象值,如果没有就会返回null
JSArray getArray(String key) 返回值JSArray对象值,如果没有就会返回null
JSObject getObject(String key) 可能会返回JSObject、JSArray、JSFunction,如果没有就会返回null
length() 数组大小

JSFunction

继承JSObject

方法 说明
JSFunction(JSContext context, JavaCallback callback) 构造函数
JSFunction(JSContext context, JavaVoidCallback callback) 构造函数
Object call(JSValue.TYPE type, JSObject receiver, JSArray parameters) 调用方法

JSContext

继承JSObject,拥有JSObject全部方法,对象本身是全局对象

方法 说明
void close() 销毁上下文
int executeIntegerScript(String source, String fileName) 执行js脚本
double executeDoubleScript(String source, String fileName) 执行js脚本
String executeStringScript(String source, String fileName) 执行js脚本
boolean executeBooleanScript(String source, String fileName) 执行js脚本
Object executeScript(String source, String fileName) 执行js脚本,可能返回Integer、Double、Boolean、String、JSArray、JSObject、JSFunction、null
void executeVoidScript(String source, String fileName) 执行js脚本,无返回值
JSArray executeArrayScript(String source, String fileName) 执行js脚本,返回值为JSArray
JSObject executeObjectScript(String source, String fileName) 执行js脚本,可能会返回JSObject、JSArray、JSFunction
You might also like...
a little hobby raspberry pi pico emulator

PICO-EMU a little raspberry pi pico emulator note: we use the provided bootrom from raspberry pi at the repo: https://github.com/raspberrypi/pico-boot

Poc to test my little friend features without any sdk

poc.vic-hack POC to test my little friend "vector" features without any sdk Ultimate goal - being able to write own firmware components without propri

A little experiment to have multicore OCaml with effects on iOS. In particular the GCD backend for eio.

Effects on iOS Very WIP & Experimental Overview A little experiment to have multicore OCaml with effects on iOS (currently just the simulator). In par

A handy little system information monitor using and ESP32 + ILI9488 TFT. Receives data over Serial Bluetooth.
A handy little system information monitor using and ESP32 + ILI9488 TFT. Receives data over Serial Bluetooth.

Bluetooth-System-Monitor A handy little system information monitor using and ESP32 + ILI9488 TFT. Receives data over Serial Bluetooth and thus giving

A little VST to test playhead reading

TempoTester This is a little AU/VST3 which just puts al the playhead information on the screen, useful for debugging DAWs. Standard instructions clone

a Little Computer 3 simulator

smol3 🖥️ a Little Computer 3 simulator smol3 is a tiny LC3 simulator written in C. It aims to be fast and correct. TODO read input binary files write

A little Trojan I wrote in a few days, creating GDI screen effects.

Monoxide A little Trojan I wrote in a few days, creating GDI screen effects. PSA This project is licensed with AGPL 3.0! In short, this means if you d

ESP32, ESP8266 based MIDI Organ using the ML_SynthTools library (little example arduino project)
ESP32, ESP8266 based MIDI Organ using the ML_SynthTools library (little example arduino project)

esp32_esp8266_organ ESP32, ESP8266 based MIDI Organ using the ML_SynthTools library (little example arduino project) link to the video The required li

Comments
  • 怎么在JS文件中获取Android传递过来的数组JSArray?

    怎么在JS文件中获取Android传递过来的数组JSArray?

    JSArray jsArray = new JSArray(jsContext).push(6).push(7).push(8); jsFunction.call(null,jsArray);

    我在js文件中,收到的数据,为啥不是数组,仅仅只是数组的第一个值? 我要怎么去做才能在js 文件中收到的是一个数组

    具体代码如下: 定义一个JS的方法(Test),然后在js文件中调用这个方法,在Android代码中:获取JSFunction,创建一个JSArray ,把这个JSArray通过JSFunction传给JS文件,结果:我在JS文件中获取的是数组的第一个数据, 求我在JS文件中怎么获取整个数组的数据?

    jsContext.registerJavaMethod(new JavaVoidCallback() { @Override public void invoke(JSObject receiver, JSArray args) { JSFunction jsFunction = (JSFunction) args.get(0); if (!jsFunction.getContext().isReleased()) { try { JSArray jsArray = new JSArray(jsContext); jsArray.push(61).push(7).push(8); jsFunction.call(null, jsArray); }catch (Throwable e){ e.printStackTrace(); } } } }, “Test”);

    opened by peienliudao 2
  • 这个依赖区分 armeabi-v7a  和 arm64-v8a吗?还是都支持?

    这个依赖区分 armeabi-v7a 和 arm64-v8a吗?还是都支持?

    大家好,这个依赖(implementation 'io.github.taoweiji.quickjs:quickjs-android:1.+')区分 armeabi-v7a 和 arm64-v8a吗?还是都支持?

    是否针对不同的架构(armeabi-v7a 和 arm64-v8a)要有不同的依赖?

    opened by peienliudao 2
  • 创建 JSArray 时,有一定几率失败

    创建 JSArray 时,有一定几率失败

    Cause: null pointer dereference x0 0000000000000000 x1 00000073317dc4b0 x2 ffffffffffffffff x3 ffffffffffffffff x4 00000000317dc4b0 x5 00000073317dc4b0 x6 00000073317040b0 x7 00000072c3509020 x8 0000000000000000 x9 0000000000000000 x10 fffffffffff4c700 x11 0000000000000002 x12 00000072c3506320 x13 00000072c3506388 x14 0000000000000000 x15 000000000000000c x16 00000072c57beac8 x17 00000072c56db6c4 x18 00000072c34f7940 x19 0000007331704000 x20 0000000000000000 x21 0000007331704000 x22 00000072c3506620 x23 00000072d5a72a0b x24 0000000000000028 x25 00000072c3509020 x26 00000073317040b0 x27 000000000000000a x28 00000072c3506390 x29 00000072c3506250 sp 00000072c35061d0 lr 00000072c56db788 pc 00000072c56d51a8

    backtrace: #01 pc 000000000003d784 (__JS_FreeValueRT+192) #02 pc 000000000003dbdc (__JS_FreeValue+40) #04 pc 000000000000e3b4 (Java_com_quickjs_QuickJSNativeImpl__1releasePtr+124) #05 pc 0000000000140350 /apex/com.android.runtime/lib64/libart.so (art_quick_generic_jni_trampoline+144) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #06 pc 0000000000137334 /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #07 pc 0000000000169eac /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #08 pc 00000000003084f8 /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #09 pc 0000000000304808 /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+692) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #10 pc 00000000005a77cc /apex/com.android.runtime/lib64/libart.so (MterpInvokeInterfaceRange+472) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #11 pc 0000000000131d14 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_interface_range+20) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #16 pc 00000000002d980c /apex/com.android.runtime/lib64/libart.so (_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_6JValueEbb.llvm.8069993068248362486+240) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #17 pc 0000000000594720 /apex/com.android.runtime/lib64/libart.so (artQuickToInterpreterBridge+1032) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #18 pc 0000000000140468 /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #19 pc 00000000020176b8 /memfd:/jit-cache (deleted) (com.quickjs.EventQueue.postVoid+184) #20 pc 0000000000137334 /apex/com.android.runtime/lib64/libart.so (art_quick_invoke_stub+548) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #21 pc 0000000000169eac /apex/com.android.runtime/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+244) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #22 pc 00000000003084f8 /apex/com.android.runtime/lib64/libart.so (art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::ShadowFrame*, unsigned short, art::JValue*)+384) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #23 pc 0000000000303758 /apex/com.android.runtime/lib64/libart.so (bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+892) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #24 pc 00000000005a3054 /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+648) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #25 pc 0000000000131814 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #27 pc 00000000005a3314 /apex/com.android.runtime/lib64/libart.so (MterpInvokeVirtual+1352) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #28 pc 0000000000131814 /apex/com.android.runtime/lib64/libart.so (mterp_op_invoke_virtual+20) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #32 pc 0000000000140468 /apex/com.android.runtime/lib64/libart.so (art_quick_to_interpreter_bridge+88) (BuildId: 7c5a82c0fd7f1b2054e72522432e1034) #33 pc 0000000002011bd0 /memfd:/jit-cache (deleted) (com.quickjs.JSContext.checkReleaseObjPtrPool+496) #34 pc 000000000200c4a8 /memfd:/jit-cache (deleted) (com.quickjs.JSContext.checkReleased+40) #35 pc 000000000201b2ac /memfd:/jit-cache (deleted) (com.quickjs.JSValue.+220)

    opened by adoutlove 1
  • await 语法支持有问题,会阻塞后续逻辑

    await 语法支持有问题,会阻塞后续逻辑

    测试代码如下:

    jsContext.executeVoidScript("console.log(\"Hello World\");\n" +
                                    "function testAsync(params) {\n" +
                                    "    console.log(\"test Async start\");\n" +
                                    "    return new Promise(function (resolve, reject) {\n" +
                                    "        resolve(\"done\");\n" +
                                    "    });\n" +
                                    "}\n" +
                                    "\n" +
                                    "async function main(){\n" +
                                    "    var t = await testAsync(11);\n" +
                                    "    console.log(\"test finish\"+t);\n" +
                                    "}\n" +
                                    "main();",null);
    

    日志输出如下,test finish 没有输出 D/QuickJS: Hello World D/QuickJS: test Async start

    opened by 2houyu 3
Releases(1.3.0)
Owner
Wiki
跨平台、动态化技术探索
Wiki
Apex cheat without R/W. can implement your own R/W and it will work fine

pubApexCheat Apex cheat without R/W. can implement your own R/W and it will work fine. will update readme later Aimbot Prediction and imGui draw funct

null 23 Nov 10, 2022
LLVM bindings for Node.js/JavaScript/TypeScript

llvm-bindings LLVM bindings for Node.js/JavaScript/TypeScript Supported OS macOS Ubuntu Windows Supported LLVM methods listed in the TypeScript defini

ApsarasX 250 Dec 18, 2022
Elk is a tiny embeddable JavaScript engine that implements a small but usable subset of ES6

Elk is a tiny embeddable JavaScript engine that implements a small but usable subset of ES6. It is designed for microcontroller development. Instead of writing firmware code in C/C++, Elk allows to develop in JavaScript. Another use case is providing customers with a secure, protected scripting environment for product customisation.

Cesanta Software 1.5k Jan 8, 2023
Header-only ECMAScript (JavaScript) compatible regular expression engine

SRELL (std::regex-like library) is a regular expression template library for C++ and has native support for UTF-8, UTF-16, and UTF-32. This is up-to-d

Dmitry Atamanov 4 Mar 11, 2022
Embedded JavaScript engine for C/C++

mJS: Restricted JavaScript engine Overview mJS is designed for microcontrollers with limited resources. Main design goals are: small footprint and sim

Cesanta Software 1.7k Dec 30, 2022
A customized LGL Android mod menu, containing ESP only for PUBG Mobile 1.3.0 for Android

PUBG Mobile ESP Mod Menu A customized LGL mod menu, containing ESP only for PUBG Mobile 1.3.0 for Android. Everything are fixed so it works with both

null 42 Mar 19, 2022
First open source android modding library for Geometry Dash Based on Hooking-and-Patching-android-template

Android-ML First open source android modding library for Geometry Dash Based on Hooking-and-Patching-android-template Installation Download this githu

BlackTea ML 21 Jul 17, 2022
A repository for experimenting with elf loading and in-place patching of android native libraries on non-android operating systems.

droidports: A repository for experimenting with elf loading and in-place patching of android native libraries on non-android operating systems. Discla

João Henrique 26 Dec 15, 2022
Android NDK samples with Android Studio

NDK Samples This repository contains Android NDK samples with Android Studio C++ integration. These samples use the new CMake Android plugin with C++

Android 9.2k Dec 27, 2022
Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

Terra Informatica Software, Inc 2.5k Dec 23, 2022