Giter Site home page Giter Site logo

zipline's Introduction

Zipline

This library streamlines using Kotlin/JS libraries from Kotlin/JVM and Kotlin/Native programs. It makes it fetching code as easy as fetching data:

  • For continuous deployment within mobile apps, just like we do for servers and web apps. It'd be simpler to do continuous deploys via the app stores! But that process is too slow and we can't guarantee that user’s devices will update immediately.
  • For user-customizable behavior and plugin systems
  • For updating business rules, like pricing or payments
  • For fresh content like games

Zipline works by embedding the QuickJS JavaScript engine in your Kotlin/JVM or Kotlin/Native program. It's a small and fast JavaScript engine that's well-suited to embedding in applications.

(Looking for Duktape Android?)

Code Example

Let's make a trivia game that has fresh questions every day, even if our users don't update their apps. We define our interface in commonMain so that we can call it from Kotlin/JVM and implement it in Kotlin/JS.

interface TriviaService : ZiplineService {
  fun games(): List<TriviaGame>
  fun answer(questionId: String, answer: String): AnswerResult
}

Next we implement it in jsMain:

class RealTriviaService : TriviaService {
  // ...
}

Let's connect the implementation running in Kotlin/JS to the interface running in Kotlin/JVM. In jsMain we define an exported function to bind the implementation:

@JsExport
fun launchZipline() {
  val zipline = Zipline.get()
  zipline.bind<TriviaService>("triviaService", RealTriviaService())
}

Now we can start a development server to serve our JavaScript to any running applications that request it.

$ ./gradlew -p samples trivia:trivia-js:serveDevelopmentZipline --info --continuous

Note that this Gradle won't ever reach 100%. That's expected; we want the development server to stay on. Also note that the --continuous flag will trigger a re-compile whenever the code changes.

You can see the served application manifest at localhost:8080/manifest.zipline.json. It references all the code modules for the application.

In jvmMain we need write a program that downloads our Kotlin/JS code and calls it. We use ZiplineLoader which handles code downloading, caching, and loading. We create a Dispatcher to run Kotlin/JS on. This must be a single-threaded dispatcher as each Zipline instance must be confined to a single thread.

suspend fun launchZipline(dispatcher: CoroutineDispatcher): Zipline {
  val manifestUrl = "http://localhost:8080/manifest.zipline.json"
  val loader = ZiplineLoader(
    dispatcher,
    ManifestVerifier.NO_SIGNATURE_CHECKS,
    OkHttpClient(),
  )
  return loader.loadOnce("trivia", manifestUrl)
}

Now we build and run the JVM program to put it all together. Do this in a separate terminal from the development server!

$ ./gradlew -p samples trivia:trivia-host:shadowJar
java -jar samples/trivia/trivia-host/build/libs/trivia-host-all.jar

Interface bridging

Zipline makes it easy to share interfaces with Kotlin/JS. Define an interface in commonMain, implement it in Kotlin/JS, and call it from the host platform. Or do the opposite: implement it on the host platform and call it from Kotlin/JS.

Bridged interfaces must extend ZiplineService, which defines a single close() method to release held resources.

By default, arguments and return values are pass-by-value. Zipline uses kotlinx.serialization to encode and decode values passed across the boundary.

Interface types that extend from ZiplineService are pass-by-reference: the receiver may call methods on a live instance.

Interface functions may be suspending. Internally Zipline implements setTimeout() to make asynchronous code work as it's supposed to in Kotlin/JS.

Zipline also supports Flow<T> as a parameter or return type. This makes it easy to build reactive systems.

Fast

One potential bottleneck of embedding JavaScript is waiting for the engine to compile the input source code. Zipline precompiles JavaScript into efficient QuickJS bytecode to eliminate this performance penalty.

Another bottleneck is waiting for code to download. Zipline addresses this with support for modular applications. Each input module (Like Kotlin's standard, serialization, and coroutines libraries) is downloaded concurrently. Each downloaded module is cached. Modules can also be embedded with the host application to avoid any downloads if the network is unreachable. If your application module changes more frequently than your libraries, users only download what's changed.

If you run into performance problems in the QuickJS runtime, Zipline includes a sampling profiler. You can use this to get a breakdown of how your application spends its CPU time.

Developer-Friendly

Zipline implements console.log by forwarding messages to the host platform. It uses android.util.Log on Android, java.util.logging on JVM, and stdout on Kotlin/Native.

Zipline integrates Kotlin source maps into QuickJS bytecode. If your process crashes, the stacktrace will print .kt files and line numbers. Even though there's JavaScript underneath, developers don't need to interface with .js files.

After using a bridged interface it must be closed so the peer object can be garbage collected. This is difficult to get right, so Zipline borrows ideas from LeakCanary and aggressively detects when a close() call is missed.

Secure

Zipline supports EdDSA Ed25519 and ECDSA P-256 signatures to authenticate downloaded libraries.

Set up is straightforward. Generate an EdDSA key pair. A task for this is installed with the Zipline Gradle plugin.

$ ./gradlew :generateZiplineManifestKeyPairEd25519
...
---------------- ----------------------------------------------------------------
      ALGORITHM: Ed25519
     PUBLIC KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    PRIVATE KEY: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
---------------- ----------------------------------------------------------------
...

Put the private key on the build server and configure it to sign builds:

zipline {
  signingKeys {
    create("key1") {
      privateKeyHex.set(...)
      algorithmId.set(app.cash.zipline.loader.SignatureAlgorithmId.Ed25519)
    }
  }
}

Put the public key in each host application and configure it to verify signatures:

val manifestVerifier = ManifestVerifier.Builder()
  .addEd25519("key1", ...)
  .build()
val loader = ZiplineLoader(
  manifestVerifier = manifestVerifier,
  ...
)

Both signing and verifying accept multiple keys to support key rotation.

Zipline is designed to run your organization's code when and where you want it. It does not offer a sandbox or process-isolation and should not be used to execute untrusted code.

Trust Model for Signatures

It is essential to keep in mind that this design puts implicit trust on:

  1. The Host Application that verifies the signatures.
  2. The Build Server that generates the signature(Has access to the signing keys)

It does not protect against any kind of compromise of the above.

Also It does not yet provide a mechanism to outlaw older(signed) versions of executable code that have known problems.

Speeding Up Hot-Reload

There are a few things you can do to make sure that hot-reload is running as fast as it can:

  1. Ensure you are running Gradle 7.5 or later (previous versions had a delay in picking up changed files).
  2. In your app's gradle.properties add kotlin.incremental.js.ir=true to enable Kotlin/JS incremental compile.
  3. In your app's gradle.properties add org.gradle.unsafe.configuration-cache=true to enable the Gradle configuration cache.
  4. In your app's build.gradle.kts add tasks.withType(DukatTask::class) { enabled = false } to turn off the Dukat task if you are not using TypeScript type declarations.

Requirements

Zipline works on Android 4.3+ (API level 18+), Java 8+, and Kotlin/Native.

Zipline uses unstable APIs in its implementation and is sensitive to version updates for these components.

Component Supported Version Notes
Kotlin Compiler 2.0.0 Kotlin compiler plugins do not yet have a stable API.
Kotlin Serialization 1.6.3 For decodeFromDynamic(), encodeToDynamic(), and ContextualSerializer.
Kotlin Coroutines 1.8.1 For transformLatest(), Deferred.getCompleted(), and CoroutineStart.ATOMIC.

We intend to use stable APIs as soon as they are available.

We intend to keep Zipline host and runtime releases interoperable so you can upgrade each independently.

Host Zipline Version Supported Runtime Zipline Versions
0.x Exact same 0.x version as the host.
1.x Any 1.x version.

License

Copyright 2015 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

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.

Duktape-Android

This project was previously known as Duktape-Android and packaged the Duktape JavaScript engine for Android. The Duktape history is still present in this repo as are the release tags. Available versions are listed on Maven central.

zipline's People

Contributors

adrw avatar alexszlavik avatar bnorm avatar bwalter avatar cashguy avatar chrisbanes avatar colinrtwhite avatar dependabot[bot] avatar eekboom avatar efirestone avatar egorand avatar f2janyway avatar goooler avatar jakewharton avatar jingibus avatar mattprecious avatar michaelevans avatar nikeorever avatar nmahendru avatar oldergod avatar renovate[bot] avatar rnett avatar robxyy avatar saket avatar shabinder avatar shawnzurbrigg avatar swankjesse avatar veyndan avatar xianguang-zhou avatar yissachar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zipline's Issues

Duktape error when build

JNI error:
/Users/***/Workspace/github/duktape-android/duktape/src/main/jni/duktape-jni.cpp Error:(77, 20) error: use of undeclared identifier 'timegm'; did you mean 'time'? Error:(77, 27) error: cannot initialize a parameter of type 'time_t *' (aka 'long *') with an rvalue of type 'tm *'

Support returning double and boolean from evaluate

The return value of duktape.evaluate returns null when not a string:

duktape.evaluate("2 + 3"); // returns null

This is a bit tricky if you're not aware of it.

It would be great when evaluate would also allow returning primitives like double and boolean, maybe like this:

Double result = duktape.evaluate("2 + 3", Double.class);

Rhino over Duktape

Hi,

I was searching for a JS engine for Android and it seems that Rhino is ~10% more efficient than Duktape. What do you think about it? Maybe a real benchmark could be helpful...

Gameboy octane test fails

identifier 'gameboy_rom' undefined

gbemu-part2 has the gameboy_rom var at the bottom as a very long string

Object.assign() crash

Executing the following javascript, I hava a duktape crash.
val duktape = Duktape.create()
duktape.evaluate("var aa = {}; Object.assign({}, aa);")

This is the stacktrace:
06-11 14:08:26.391 13157-13543/com.example.jsduktape E/AndroidRuntime: FATAL EXCEPTION: Thread-7
Process: com.example.jsduktape, PID: 13157
com.squareup.duktape.DuktapeException: TypeError: undefined not callable
at JavaScript.eval(?:1)
at com.squareup.duktape.Duktape.evaluate(Native Method)
at com.squareup.duktape.Duktape.evaluate(Duktape.java:69)
at com.example.jsduktape.MainActivity$onCreate$1.run(MainActivity.kt:56)
at java.lang.Thread.run(Thread.java:764)

If I execute the same javascript on a WebView, there are no problems.

Call Java functions from duktape

It would be useful to be able to call native Java/Android functions from within JavaScript, similar to how Rhino allows importing native functions.

For my specific case there is no need to implement full support for conversion between Java and JS objects, it would be enough to just be able to call a function with primitive arguments like double, String, int.

java.lang.UnsatisfiedLinkError: no duktape in java.library.path

Hello. I made some JUnit tests and I get this error when testing the Duktape methods I've made.

I don't get any error when building the android application, but when testing. I need to test to know if it works as excepted.

I tried including System.getProperties()["java.library.path"] = "${System.getProperty("user.dir")}\\build\\" in the same test, and System.getProperty("java.library.path") returns the excepted value.

local reference table overflow (max=512) error

when I call duktape.set ("someName" , interface.class, interface instance );

local reference table overflow (max=512) error occured

interface method has 40 methods.

and if I set method count 30, the error is not occured.

so I'm call set two interface.class.

the first interface has 20 methods. and second interfacde has 20 method.

Is it a bug?

JNI ERROR (app bug): accessed deleted global reference

09-10 12:11:44.183 7478 8530 E     art                                          JNI ERROR (app bug): accessed deleted global reference 0x100752
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: use of deleted global reference 0x100752
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]     from long com.squareup.duktape.Duktape.createContext()
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410] "RxIoScheduler-20" daemon prio=5 tid=82 Runnable
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | group="main" sCount=0 dsCount=0 obj=0x339f5b20 self=0x7f0474d000
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | sysTid=8530 nice=0 cgrp=bg_non_interactive sched=0/0 handle=0x7f60d03440
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | state=R schedstat=( 100964150 70105114 208 ) utm=9 stm=1 core=5 HZ=100
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | stack=0x7f60c01000-0x7f60c03000 stackSize=1037KB
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   | held mutexes= "mutator lock"(shared held)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #00 pc 000000000048a5b0  /system/lib64/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+200)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #01 pc 0000000000459358  /system/lib64/libart.so (_ZNK3art6Thread4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEP12BacktraceMap+224)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #02 pc 000000000030d764  /system/lib64/libart.so (_ZN3art9JavaVMExt8JniAbortEPKcS2_+1004)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #03 pc 000000000030e138  /system/lib64/libart.so (_ZN3art9JavaVMExt9JniAbortFEPKcS2_z+224)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #04 pc 000000000045988c  /system/lib64/libart.so (_ZNK3art6Thread13DecodeJObjectEP8_jobject+548)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #05 pc 0000000000351d3c  /system/lib64/libart.so (_ZN3art3JNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+464)
09-10 12:11:44.263 7478 8530 F     art                                          art/runtime/java_vm_ext.cc:410]   native: #06 pc 00000000001529c8  /system/lib64/libart.so (_ZN3art8CheckJNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_+560) 

Exception when trying to throw exception

The JS is throwing an exception and Duktape is throwing when trying to handle it.

A/art: art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: JNI FindClass called with pending exception com.squareup.duktape.DuktapeException: DoubleError: error in error handling
A/art: art/runtime/java_vm_ext.cc:410]   at java.lang.Object com.squareup.duktape.Duktape.call(long, long, java.lang.Object, java.lang.Object[]) (Duktape.java:-2)
A/art: art/runtime/java_vm_ext.cc:410]   at java.lang.Object com.squareup.duktape.Duktape.access$100(long, long, java.lang.Object, java.lang.Object[]) (Duktape.java:29)
A/art: art/runtime/java_vm_ext.cc:410]   at java.lang.Object com.squareup.duktape.Duktape$1.invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) (Duktape.java:131)
A/art: art/runtime/java_vm_ext.cc:410]   at java.lang.Object java.lang.reflect.Proxy.invoke(java.lang.reflect.Proxy, java.lang.reflect.Method, java.lang.Object[]) (Proxy.java:393)
art  F  art/runtime/java_vm_ext.cc:410] JNI DETECTED ERROR IN APPLICATION: thread Thread[71,tid=4643,Native,Thread*=0xda16a400,peer=0x13253400,"RxIoScheduler-34"] using JNIEnv* from thread Thread[71,tid=4643,Native,T
        hread*=0xda16a400,peer=0x13253400,"RxIoScheduler-34"]
     F  art/runtime/java_vm_ext.cc:410]     in call to FindClass
     F  art/runtime/java_vm_ext.cc:410]     from java.lang.Object com.squareup.duktape.Duktape.call(long, long, java.lang.Object, java.lang.Object[])
     F  art/runtime/java_vm_ext.cc:410] "RxIoScheduler-34" daemon prio=5 tid=71 Runnable
     F  art/runtime/java_vm_ext.cc:410]   | group="main" sCount=0 dsCount=0 obj=0x13253400 self=0xda16a400
     F  art/runtime/java_vm_ext.cc:410]   | sysTid=4643 nice=0 cgrp=default sched=0/0 handle=0xd94b0930
     F  art/runtime/java_vm_ext.cc:410]   | state=R schedstat=( 19140299 26291000 41 ) utm=0 stm=1 core=1 HZ=100
     F  art/runtime/java_vm_ext.cc:410]   | stack=0xd93ae000-0xd93b0000 stackSize=1038KB
     F  art/runtime/java_vm_ext.cc:410]   | held mutexes= "mutator lock"(shared held)
     F  art/runtime/java_vm_ext.cc:410]   native: #00 pc 0058b0e2  /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::ArtMethod*, void*)+2
        26)
     F  art/runtime/java_vm_ext.cc:410]   native: #01 pc 00550d2e  /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+286)
     F  art/runtime/java_vm_ext.cc:410]   native: #02 pc 003a489f  /system/lib/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1247)
     F  art/runtime/java_vm_ext.cc:410]   native: #03 pc 003a5f1c  /system/lib/libart.so (art::JavaVMExt::JniAbortV(char const*, char const*, char*)+116)
     F  art/runtime/java_vm_ext.cc:410]   native: #04 pc 00163a10  /system/lib/libart.so (art::ScopedCheck::AbortF(char const*, ...)+62)
     F  art/runtime/java_vm_ext.cc:410]   native: #05 pc 0016d90c  /system/lib/libart.so (art::ScopedCheck::CheckThread(_JNIEnv*)+1692)
     F  art/runtime/java_vm_ext.cc:410]   native: #06 pc 0016e4e1  /system/lib/libart.so (art::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::JniValueType*) (.constprop.114)+1489)
     F  art/runtime/java_vm_ext.cc:410]   native: #07 pc 001721e5  /system/lib/libart.so (art::CheckJNI::FindClass(_JNIEnv*, char const*)+601)
     F  art/runtime/java_vm_ext.cc:410]   native: #08 pc 00046200  /data/app/com.squareup.cash.beta.debug-2/lib/x86/libduktape.so (???)
     F  art/runtime/java_vm_ext.cc:410]   native: #09 pc 00041970  /data/app/com.squareup.cash.beta.debug-2/lib/x86/libduktape.so (???)
     F  art/runtime/java_vm_ext.cc:410]   native: #10 pc 000412c0  /data/app/com.squareup.cash.beta.debug-2/lib/x86/libduktape.so (???)
     F  art/runtime/java_vm_ext.cc:410]   native: #11 pc 00040f4c  /data/app/com.squareup.cash.beta.debug-2/lib/x86/libduktape.so (???)
     F  art/runtime/java_vm_ext.cc:410]   native: #12 pc 00045f18  /data/app/com.squareup.cash.beta.debug-2/lib/x86/libduktape.so (Java_com_squareup_duktape_Duktape_call+72)
     F  art/runtime/java_vm_ext.cc:410]   native: #13 pc 011b4d1e  /data/app/com.squareup.cash.beta.debug-2/oat/x86/base.odex (java.lang.Object com.squareup.duktape.Duktape.call(long, long, java.lang.Object, java.lan
        g.Object[])+194)
     F  art/runtime/java_vm_ext.cc:410]   native: #14 pc 011b4af7  /data/app/com.squareup.cash.beta.debug-2/oat/x86/base.odex (java.lang.Object com.squareup.duktape.Duktape.access$100(long, long, java.lang.Object, ja
        va.lang.Object[])+91)
     F  art/runtime/java_vm_ext.cc:410]   native: #15 pc 011b474c  /data/app/com.squareup.cash.beta.debug-2/oat/x86/base.odex (java.lang.Object com.squareup.duktape.Duktape$1.invoke(java.lang.Object, java.lang.reflec
        t.Method, java.lang.Object[])+352)
     F  art/runtime/java_vm_ext.cc:410]   native: #16 pc 0035c2f5  /data/dalvik-cache/x86/system@[email protected] (???)
     F  art/runtime/java_vm_ext.cc:410]   at com.squareup.duktape.Duktape.call(Native method)
     F  art/runtime/java_vm_ext.cc:410]   at com.squareup.duktape.Duktape.access$100(Duktape.java:29)
     F  art/runtime/java_vm_ext.cc:410]   at com.squareup.duktape.Duktape$1.invoke(Duktape.java:131)
     F  art/runtime/java_vm_ext.cc:410]   at java.lang.reflect.Proxy.invoke(Proxy.java:393)

How to run js method with params

If in java application, run js method in java, can send some params such as text or code,but i can't find any type to set params in using duktape.evaluate.
For Example
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("JavaScript");
engine.eval(new java.io.FileReader("test.js"));
Invocable inv = (Invocable)engine;
Object a = inv.invokeFunction("get", text, code);

Use external JS library

Hello,

Can I attach somehow and use external javascript libraries like analytics.js and firebase.js (from Google) with Duktape?

Thanks.

link error when build for android

I just build with command:

./gradlew build

and the error occurs:

/Volumes/Android/buildbot/out_dirs/aosp-ndk-r11-release/build/tmp/build-57861/build-libc++/ndk/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/src/cxa_handlers.cpp:112: error: undefined reference to '__atomic_exchange_4'
/Volumes/Android/buildbot/out_dirs/aosp-ndk-r11-release/build/tmp/build-57861/build-libc++/ndk/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/src/cxa_default_handlers.cpp:106: error: undefined reference to '__atomic_exchange_4'
/Volumes/Android/buildbot/out_dirs/aosp-ndk-r11-release/build/tmp/build-57861/build-libc++/ndk/sources/cxx-stl/llvm-libc++/../llvm-libc++abi/libcxxabi/src/cxa_default_handlers.cpp:117: error: undefined reference to '__atomic_exchange_4'
collect2: error: ld returned 1 exit status

:duktape:linkDuktapeArmeabiDebugSharedLibrary FAILED

Get and set values to context

Are there any plans to implement methods to get and set values (variables and functions) on a duktape context?
I need to get a javascript function from Java code and invoke it with arguments?
Do you guys plan to do this soon? Otherwise I could open a pull request.

DuktapeException: TypeError: cannot read property 'prototype' of undefined

   Caused by: com.squareup.duktape.DuktapeException: TypeError: cannot read property 'prototype' of undefined
                                                                    at JavaScript.runInContext(?:43226)
                                                                    at JavaScript.s(?:1)
                                                                    at com.squareup.duktape.Duktape.evaluate(Native Method)
                                                                    at com.squareup.duktape.Duktape.evaluate(Duktape.java:69)

here is my code:

val duktape = Duktape.create()
        try {
            duktape.evaluate(assets.open("bundle.js").reader(Charset.forName("UTF-8")).readText())
            LogHelper.LogE("--->" + duktape.evaluate("generateAddress").toString())
        } finally {
            duktape.close()
        }
Address.prototype.isPayToScriptHash = function() {
  return this.type === Address.PayToScriptHash;
};

JNI ERROR (app bug): local reference table overflow (max=512)

I have setup a very simple bridge for the Foo interface, then tried to go through the bridge 1000 times in a for loop from JS to Java:

// 'foo' is a Ducktape bridged object. Java: duktape.set("foo", FooExport.class, foo);
for (var i = 0; i < 1000; i++) {
    var hello = foo.say('hello');
}

I get:
screen shot 2017-06-01 at 7 01 18 pm

I am trying to build a layer on top of Duktape to help bridge around more complex Objects. For this, a lot of calls to and from native are needed. The limitation of the reference table to 512 entries for each evaluate(..) call is really not enough.

I guess you should clean the references on the Native side immediately after the String result was returned to JS, and not wait until the evaluate() function has finished execution.

Did the same test within a WebView, and the issue did not appear.

Is this a known issue, is there any workaround?

String.fromCharCode wrong result

It seems String.fromCharCode returns wrong results, or at least they differ from other JS engines.
Calling String.fromCharCode(65) returns a strange symbol instead of the expected 'A'.

Is this expected behaviour, a Duktape issue or related to the Java wrapper?

makefile.cmdline chokes on javascript-obfuscator

Hi

when we use the selfDefending on javascript-obfuscator the regex chokes

function outputMyNumber(showThis)
{
console.log(showThis);
}
function hello()
{
var getNumber = function (b) {return b+ 3; }
var thenumber = getNumber(2);
outputMyNumber(thenumber);
}
hello()

obfuscator: {
options: {
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: false,
disableConsoleOutput: false,
identifierNamesGenerator: 'hexadecimal',
log: true,
renameGlobals: false,
rotateStringArray: true,
selfDefending: true,
stringArray: true,
stringArrayEncoding: 'base64',
stringArrayThreshold: 0.75,
unicodeEscapeSequence: false,
target: 'browser'
},

function outputMyNumber(_0x393fc5){console'log';}function hello(){var _0x246e30=function(){var _0xb2ee37=!![];return function(_0x2a1c07,_0x39a818){var _0x47081b=_0xb2ee37?function(){if(_0x39a818){var _0x461e24=_0x39a818'apply';_0x39a818=null;return _0x461e24;}}:function(){};_0xb2ee37=![];return _0x47081b;};}();var _0x78fdcf=function(_0x408fe3){var _0x1a1f63=_0x246e30(this,function(){var _0x49075f=function(){return'\x64\x65\x76';},_0x57969d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var _0x23f862=function(){var _0x45fb57=new RegExp('\w+\s*(){\w+\s['|"].+['|"];?\s*}');return!_0x45fb57'\x74\x65\x73\x74';};var _0x532ab5=function(){var _0x130be7=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return _0x130be7'\x74\x65\x73\x74';};var _0x4e7fde=function(_0x47bb06){var _0x35aeea=-0x1>>0x1+0xff%0x0;if(_0x47bb06'\x69\x6e\x64\x65\x78\x4f\x66'){_0x54673c(_0x47bb06);}};var _0x54673c=function(_0x192be0){var _0x2eb20c=-0x4>>0x1+0xff%0x0;if(_0x192be0'\x69\x6e\x64\x65\x78\x4f\x66'!==_0x2eb20c){_0x4e7fde(_0x192be0);}};if(!_0x23f862()){if(!_0x532ab5()){_0x4e7fde('\x69\x6e\x64\u0435\x78\x4f\x66');}else{_0x4e7fde('\x69\x6e\x64\x65\x78\x4f\x66');}}else{_0x4e7fde('\x69\x6e\x64\u0435\x78\x4f\x66');}});_0x1a1f63();return _0x408fe3+0x3;};var _0x333e8b=_0x78fdcf(0x2);outputMyNumber(_0x333e8b);}hello();

Date.getTimezoneOffset() returns null

It looks like the getTimezoneOffset() function on Dates is not hooked up and requires an android-specific implementation.

reproduce:

String val = duktape.evaluate("new Date().getTimezoneOffset();");
print(val); //null

the function is there, but just returns null.

Is it possible to use this library as a webView ?

I want to parse website pages with normal webView, but it is not suited for this.
I need something like okHttp requestTag, does Duktape allow this ?
Can I use Duktape like a WebView (just for parsing and navigate in websites, without showing the page on the screen) ?

Thanks in advance.

seem not allow pass ret value from java if call java from js

my JAVA code:
interface PrintInterface {
void print(String s);
String rprint(String s);
String getValue();
}
sDuktape.set("PrintInterface", PrintInterface.class, new PrintInterface() {
@OverRide
public void print(String s) {
System.out.println(s);
}
@OverRide
public String rprint(String s) {
return "java get:" + s;
}
@OverRide
public String getValue() {
return "Hello from JAVA";
}
});

my js code:
PrintInterface.print('Hello world!');

PrintInterface.print(PrintInterface.getValue());

var ret = PrintInterface.sprint('version: ' + Duktape.version);

executed result:

Hello world!
Hello from JAVA
TypeError: undefined not callable exception:com.squareup.duktape.DuktapeException: TypeError: undefined not callable

seems this line " var ret = PrintInterface.sprint('version: ' + Duktape.version);" is not allow

Identifier 'console' undefined

I get this error when attempting to do a simple console.log call.

After reading Duktape documentation, I see that it does not provide a console implementation. Is that true for duktape-android? If so, can we provide a console implementation?

JNI ERROR (app bug): local reference table overflow (max=512)

JNI ERROR (app bug): local reference table overflow (max=512)
art/runtime/indirect_reference_table.cc:132] local reference table dump:
art/runtime/indirect_reference_table.cc:132] Last 10 entries (of 512):
art/runtime/indirect_reference_table.cc:132] 511: 0x134f6250 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 510: 0x134f6220 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 509: 0x134f61f0 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 508: 0x134f61c0 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 507: 0x134f6190 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 506: 0x134f6160 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 505: 0x134f6130 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 504: 0x134f6100 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 503: 0x134f60d0 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] 502: 0x134f60a0 libcore.util.ZoneInfo
art/runtime/indirect_reference_table.cc:132] Summary:
art/runtime/indirect_reference_table.cc:132] 2 of $Proxy21 (1 unique instances)
art/runtime/indirect_reference_table.cc:132] 2 of $Proxy20 (1 unique instances)
art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Thread
art/runtime/indirect_reference_table.cc:132] 2 of java.lang.reflect.Method (2 unique instances)
art/runtime/indirect_reference_table.cc:132] 4 of java.lang.String (2 unique instances)
art/runtime/indirect_reference_table.cc:132] 1 of java.util.ArrayList
art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Object[] (1 elements)
art/runtime/indirect_reference_table.cc:132] 1 of java.lang.Object[] (2 elements)
art/runtime/indirect_reference_table.cc:132] 498 of libcore.util.ZoneInfo (498 unique instances)

I getting the above error when i am using

get(final String name, final Class type)

the type interface is this:

  interface JsBinder {

        fun androidWrapper(functionName: String, **input**: String): String

    }

the String **input** in the interface is an Array of 44 objects. Work fine when less elements in array are present.

Originally posted by @resengupta in #90 (comment)

Include the JS trace in exceptions

A simple approach would be to add it rendered on the end of the message. One could also synthesize an exception cause by building up StackTraceElements for each JS call.

When call Duktape.close() , native crash occured.

**I'm using duktape-android in Thread and multi.

when I run duktape-android about over 300 times, out of memory occured.
So I called Duktape at end of script.
When I called Duktape.close(), native crash occured.
Below is the log.**

12-18 10:00:12.897 29666-714/com.kwic.smartaibmonitormaster E/libc++abi: Pure virtual function called!
12-18 10:00:12.898 29666-714/com.kwic.smartaibmonitormaster A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 714 (Thread-4)

                                                                [ 12-18 10:00:12.899   476:  476 W/         ]
                                                                debuggerd: handling request: pid=29666 uid=10207 gid=10207 tid=714

12-18 10:00:12.972 759-759/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-18 10:00:12.973 759-759/? A/DEBUG: Build fingerprint: 'lge/lucye_lgu_kr/lucye:7.0/NRD90U/172411421f9f3:user/release-keys'
12-18 10:00:12.973 759-759/? A/DEBUG: Revision: '12'
12-18 10:00:12.973 759-759/? A/DEBUG: ABI: 'arm64'
12-18 10:00:12.973 759-759/? A/DEBUG: pid: 29666, tid: 714, name: Thread-4 >>> com.kwic.smartaibmonitormaster <<<
12-18 10:00:12.973 759-759/? A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
12-18 10:00:12.973 759-759/? A/DEBUG: x0 0000000000000000 x1 00000000000002ca x2 0000000000000006 x3 0000000000000008
12-18 10:00:12.973 759-759/? A/DEBUG: x4 ffffffffffffffff x5 8080800000000000 x6 0000000000808080 x7 fefeff2063646b6b
12-18 10:00:12.973 759-759/? A/DEBUG: x8 0000000000000083 x9 ffffffffffffffdf x10 0000000000000000 x11 0000000000000001
12-18 10:00:12.973 759-759/? A/DEBUG: x12 ffffffffffffffff x13 0000000000000000 x14 0000000000000000 x15 00357c6e098c12a3
12-18 10:00:12.973 759-759/? A/DEBUG: x16 00000075b8551ed0 x17 00000075b84fb3f4 x18 00000000ffffffff x19 00000075ac8c14f8
12-18 10:00:12.973 759-759/? A/DEBUG: x20 0000000000000006 x21 00000075ac8c1450 x22 0000000000000000 x23 00000000ffffffc8
12-18 10:00:12.973 759-759/? A/DEBUG: x24 00000075ac8bdd60 x25 00000075ac8bdc30 x26 00000075ac8bdc70 x27 0000000000000001
12-18 10:00:12.973 759-759/? A/DEBUG: x28 00000075ad48f728 x29 00000075ac8bdb40 x30 00000075b84f8884
12-18 10:00:12.973 759-759/? A/DEBUG: sp 00000075ac8bdb20 pc 00000075b84fb3fc pstate 0000000060000000
12-18 10:00:12.983 759-759/? A/DEBUG: backtrace:
12-18 10:00:12.983 759-759/? A/DEBUG: #00 pc 000000000006c3fc /system/lib64/libc.so (tgkill+8)
12-18 10:00:12.983 759-759/? A/DEBUG: #1 pc 0000000000069880 /system/lib64/libc.so (pthread_kill+64)
12-18 10:00:12.983 759-759/? A/DEBUG: #2 pc 0000000000024658 /system/lib64/libc.so (raise+24)
12-18 10:00:12.983 759-759/? A/DEBUG: #3 pc 000000000001d074 /system/lib64/libc.so (abort+52)
12-18 10:00:12.983 759-759/? A/DEBUG: #4 pc 000000000008c72c /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #5 pc 000000000008a5b0 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (__cxa_pure_virtual+16)
12-18 10:00:12.983 759-759/? A/DEBUG: #6 pc 0000000000017b64 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #7 pc 0000000000017504 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #8 pc 0000000000078d5c /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #9 pc 000000000007f564 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #10 pc 000000000007a1b0 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #11 pc 0000000000078e24 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.983 759-759/? A/DEBUG: #12 pc 0000000000021b98 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.984 759-759/? A/DEBUG: #13 pc 0000000000024fd4 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (duk_eval_raw+188)
12-18 10:00:12.984 759-759/? A/DEBUG: #14 pc 0000000000014500 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so
12-18 10:00:12.984 759-759/? A/DEBUG: #15 pc 0000000000015bf8 /data/app/com.kwic.smartaibmonitormaster-2/lib/arm64/libduktape.so (Java_com_squareup_duktape_Duktape_evaluate__JLjava_lang_String_2Ljava_lang_String_2+52)
12-18 10:00:12.984 759-759/? A/DEBUG: #16 pc 00000000001f324c /data/app/com.kwic.smartaibmonitormaster-2/oat/arm64/base.odex (offset 0x1e9000)

app crashes after duktape.close() is called

Hi,

I am using duktape to run some javascript, I have several native object injected such as setTimeout, console, etc. I also have multiple duktape instances running at the same time. Duktape instances could be called from different threads.
I got the following error and the app crashes after duktape.close() is called. Please see the log below:

08-13 16:11:52.800 16359-16359/mypackage.myapplication A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x3 in tid 16359 (x.myapplication)
08-13 16:11:52.821 16579-16579/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/sdk_gphone_x86/generic_x86:8.0.0/OSR1.170901.043/4456315:user/release-keys'
Revision: '0'
ABI: 'x86'
pid: 16359, tid: 16359, name: x.myapplication >>> mypackage.myapplication <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x3
Cause: null pointer dereference
eax 00000003 ebx 8b6b2ac4 ecx 00590000 edx ab41e400
esi 8b371640 edi af8a9230
xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b
eip 8b651bc8 ebp bf812608 esp bf8125d0 flags 00010292
08-13 16:11:52.826 16579-16579/? A/DEBUG: backtrace:
#00 pc 00050bc8 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#1 pc 00050648 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#2 pc 000504d3 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#3 pc 0004dc15 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#4 pc 00044bd0 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#5 pc 00045f11 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#6 pc 00045207 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#7 pc 00044c23 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#8 pc 000212ca /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#9 pc 0001026c /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#10 pc 0000fee5 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so (duk_safe_call+86)
#11 pc 000118bc /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so (duk_eval_raw+162)
#12 pc 0004ce21 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so
#13 pc 0004e7c9 /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/lib/x86/libduktape.so (Java_com_squareup_duktape_Duktape_evaluate__JLjava_lang_String_2Ljava_lang_String_2+71)
#14 pc 0001044e /data/app/mypackage.myapplication-D0-vsq-F3xnvRZujGrz8vQ==/oat/x86/base.odex (offset 0x10000)
#15 pc 00059fff [anon:libc_malloc:af880000]

we wish to use duk_load_function

is this in the wrapper already ? if we want to enable it are there any considerations we need to be thinking about , any potential pitfalls etc

crash in duk__expr_led function when it is armeabi with -DCMAKE_BUILD_TYPE=MinSizeRel/Release

I see duktape's support abi is armeabi-v7a and arm64-v8a in build.gradle . when I build against armeabi, and when eval a javascript, it crash in duk__expr_led function.
I set a breakpoint at switch code below:
`DUK_LOCAL void duk__expr_led(duk_compiler_ctx *comp_ctx, duk_ivalue *left, duk_ivalue *res) {
duk_hthread *thr = comp_ctx->thr;
duk_token tk;
duk_small_uint_t tok;
duk_uint32_t args; / temp variable to pass constants and flags to shared code */

/*

  • ctx->prev_token token to process with duk__expr_led()
  • ctx->curr_token updated by caller
    */

comp_ctx->curr_func.led_count++;

/* The token in the switch has already been eaten here */
tk = &comp_ctx->prev_token;
tok = tk->t;

DUK_DDD(DUK_DDDPRINT("duk__expr_led(), prev_token.t=%ld, allow_in=%ld, paren_level=%ld",
(long) tk->t, (long) comp_ctx->curr_func.allow_in, (long) comp_ctx->curr_func.paren_level));

/* XXX: default priority for infix operators is duk__expr_lbp(tok) -> get it here? */

switch (tok) {` //crash here

when I step next, It throws signal SIGSEGV: invalid address (fault address 0x164) at tok.

Can duktape parse an object?

The documentation say that "Object is supported in declarations, but the type of the actual value passed must be one of the above(boolean, int, double, string and void) or null."
Is there any way to send an Object to js?

New maven build?

Hello,

Is there any ETA when the maven build will be updated? Looks like the last update was on Sep, 2017

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.