diff --git a/CMakeLists.txt b/CMakeLists.txt index 84083d2..beccbfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,3 +29,9 @@ endif() if(ANDROID) add_subdirectory(android) endif() + +if(PROJECT_IS_TOP_LEVEL) + enable_testing() + + add_subdirectory(test) +endif() diff --git a/android/build.gradle b/android/build.gradle index 2f32500..4bebcdf 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -16,7 +16,7 @@ android { externalNativeBuild { cmake { targets "bare_kit" - arguments "-DCMAKE_MODULE_PATH=$System.env.CMAKE_MODULE_PATH", "-DANDROID_STL=none" + arguments "-DCMAKE_MODULE_PATH=$System.env.CMAKE_MODULE_PATH", "-DANDROID_STL=c++_shared" } } } diff --git a/android/src/main/java/to/holepunch/bare/kit/Worklet.java b/android/src/main/java/to/holepunch/bare/kit/Worklet.java index 6cd99e7..a8d98dd 100644 --- a/android/src/main/java/to/holepunch/bare/kit/Worklet.java +++ b/android/src/main/java/to/holepunch/bare/kit/Worklet.java @@ -30,12 +30,19 @@ private interface NativePushCallback { public static class Options { public int memoryLimit = 0; + public String assets = null; public Options memoryLimit (int memoryLimit) { this.memoryLimit = memoryLimit; return this; } + + public Options + assets (String assets) { + this.assets = assets; + return this; + } } private ByteBuffer handle; @@ -46,13 +53,13 @@ public static class Options { public Worklet(Options options) { if (options == null) options = new Options(); - handle = init(options.memoryLimit); + handle = init(options.memoryLimit, options.assets); handler = Handler.createAsync(Looper.getMainLooper()); } private native ByteBuffer - init (int memoryLimit); + init (int memoryLimit, String assets); private native void start (ByteBuffer handle, String filename, ByteBuffer source, int len, String[] arguments); diff --git a/android/src/main/jni/Worklet.c b/android/src/main/jni/Worklet.c index 7839dfb..9f9e71e 100644 --- a/android/src/main/jni/Worklet.c +++ b/android/src/main/jni/Worklet.c @@ -17,18 +17,28 @@ typedef struct { } bare_worklet_push_context_t; JNIEXPORT jobject JNICALL -Java_to_holepunch_bare_kit_Worklet_init (JNIEnv *env, jobject self, jint jmemory_limit) { +Java_to_holepunch_bare_kit_Worklet_init (JNIEnv *env, jobject self, jint jmemory_limit, jobject jassets) { int err; bare_worklet_t *worklet = malloc(sizeof(bare_worklet_t)); - bare_worklet_options_t options = { - .memory_limit = (int) jmemory_limit, - }; + bare_worklet_options_t options; + + options.memory_limit = (int) jmemory_limit; + + if ((*env)->IsSameObject(env, jassets, NULL)) { + options.assets = NULL; + } else { + options.assets = (*env)->GetStringUTFChars(env, jassets, NULL); + } err = bare_worklet_init(worklet, &options); assert(err == 0); + if (options.assets) { + (*env)->ReleaseStringUTFChars(env, jassets, options.assets); + } + jobject handle = (*env)->NewDirectByteBuffer(env, (void *) worklet, sizeof(bare_worklet_t)); return handle; diff --git a/apple/BareKit/BareKit.h b/apple/BareKit/BareKit.h index 95789ae..a9049fe 100644 --- a/apple/BareKit/BareKit.h +++ b/apple/BareKit/BareKit.h @@ -9,6 +9,7 @@ @interface BareWorkletConfiguration : NSObject @property NSUInteger memoryLimit; +@property(nullable, copy) NSString *assets; + (BareWorkletConfiguration *_Nullable)defaultWorkletConfiguration; diff --git a/apple/BareKit/BareKit.m b/apple/BareKit/BareKit.m index 8df390d..c91590c 100644 --- a/apple/BareKit/BareKit.m +++ b/apple/BareKit/BareKit.m @@ -93,6 +93,7 @@ - (_Nullable instancetype)init { if (self) { _memoryLimit = 0; + _assets = nil; } return self; @@ -118,8 +119,10 @@ - (_Nullable instancetype)initWithConfiguration:(BareWorkletConfiguration *_Null if (options) { _options.memory_limit = options.memoryLimit; + _options.assets = [options.assets UTF8String]; } else { _options.memory_limit = 0; + _options.assets = nil; } int err; diff --git a/package-lock.json b/package-lock.json index 5ef8f17..46f4855 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,16 @@ "name": "bare-kit", "license": "Apache-2.0", "dependencies": { + "bare-bundle": "^1.4.0", + "bare-crypto": "^1.2.8", "bare-events": "^2.4.2", + "bare-fs": "^3.0.2", "bare-ipc": "^1.0.0", - "bare-rpc": "^0.1.0" + "bare-module": "^4.3.0", + "bare-module-resolve": "^1.6.2", + "bare-path": "^3.0.0", + "bare-rpc": "^0.1.0", + "bare-url": "^2.0.1" }, "devDependencies": { "standard": "^17.0.0" @@ -32,9 +39,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "license": "MIT", "engines": { @@ -66,9 +73,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", "engines": { @@ -76,14 +83,14 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -151,6 +158,13 @@ "node": ">= 8" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -413,9 +427,9 @@ } }, "node_modules/b4a": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", - "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", "license": "Apache-2.0" }, "node_modules/balanced-match": { @@ -425,12 +439,41 @@ "dev": true, "license": "MIT" }, + "node_modules/bare-bundle": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/bare-bundle/-/bare-bundle-1.6.0.tgz", + "integrity": "sha512-94m0wjpbcU+srXjqWTz0qgreUhsYuoYcSmZj5IATL0DA3YF41s4cd2iO+BV0M0E07LbgqAqY23rWRCUUUBu9BA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/bare-crypto": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/bare-crypto/-/bare-crypto-1.2.8.tgz", + "integrity": "sha512-cew18kB4N9gybGjUPs5R4ZWEsS7geEBJHdULl1EBLTFjjTWGodx1gV6J+uoRWMcQtENs3DjYfwEJyY0kvHMVLg==", + "license": "Apache-2.0", + "dependencies": { + "bare-stream": "^2.0.0" + } + }, "node_modules/bare-events": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", - "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", "license": "Apache-2.0" }, + "node_modules/bare-fs": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-3.0.2.tgz", + "integrity": "sha512-QWw1LQkaRvhZYbicfPdY7srt0Q5MO6BAQnomvBylVdgg+xAVse4sbYbNVtN0RdX6A6nimrykipER6NJDcR939g==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^3.0.0", + "bare-stream": "^2.0.0" + } + }, "node_modules/bare-ipc": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/bare-ipc/-/bare-ipc-1.0.0.tgz", @@ -441,10 +484,50 @@ "bare-stream": "^2.1.3" } }, + "node_modules/bare-module": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/bare-module/-/bare-module-4.3.1.tgz", + "integrity": "sha512-QsR2Oyr1xbpfAJGrTdxnRQexdeOPYRO2HjvxWW8LberDe5M/f/m93/+kTxanzUM9r80TiLADogxwDLM9oQtjAg==", + "license": "Apache-2.0", + "dependencies": { + "bare-bundle": "^1.3.0", + "bare-module-resolve": "^1.6.0", + "bare-path": "^3.0.0", + "bare-url": "^2.0.1", + "cjs-module-lexer": "^1.2.3" + } + }, + "node_modules/bare-module-resolve": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/bare-module-resolve/-/bare-module-resolve-1.6.2.tgz", + "integrity": "sha512-bMQaTm9gYvDwJaXDsZPeT8jriiT/wnHy4V/wFoOxEci/OMe+SqECUKeZlchho0FOKvDMlWxzFtUiI4Nv6iozkw==", + "license": "Apache-2.0", + "dependencies": { + "semifies": "^1.0.0" + } + }, + "node_modules/bare-os": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.2.0.tgz", + "integrity": "sha512-IR5QjWR4sXBHI8VrXyeJ8BwwTRMlerNROVQRUJXwYd5sCHfxxTzpnKp1bJfe3Mg/MfWSzqNbpDC8sR9+X2LJkQ==", + "license": "Apache-2.0", + "engines": { + "bare": ">=1.6.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "dependencies": { + "bare-os": "^3.0.1" + } + }, "node_modules/bare-pipe": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-3.3.2.tgz", - "integrity": "sha512-uam6mBRdSFaoIBwM7X3/B5+lQrVN6X2b9HIPcv6PGWm6KsNCIY6FFgGSk3xOeCLNYO52DhoQLqD8K15cjuNxpQ==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/bare-pipe/-/bare-pipe-3.3.7.tgz", + "integrity": "sha512-PSf7RuqfWR0U2c7QHuhgNoRw5qNGElggAeeQXMnoBqRrlYp2iZav5tTYcg0rnZkhefBZ9bOujvtR8qac8K2Zkg==", "license": "Apache-2.0", "dependencies": { "bare-events": "^2.0.0", @@ -452,26 +535,35 @@ } }, "node_modules/bare-rpc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bare-rpc/-/bare-rpc-0.1.0.tgz", - "integrity": "sha512-VCFCYSl7U0Z2gJMC9Iqy+94xHsvBsP/3OEjD3UiBaPm7WW2YNw0u42kllsTA4kucVrsSvBFIQ7Mt8kts2O0LdA==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/bare-rpc/-/bare-rpc-0.1.2.tgz", + "integrity": "sha512-xLp4ntEi9uJ4zRnEkNULyeg2UvjOkUr1JgAdgQkXr3pHnMK3CSXwdSLIPBQNjVrKIGumG9u6jGtUcf4o/bqCfw==", "license": "Apache-2.0", "dependencies": { + "b4a": "^1.6.6", "bare-stream": "^2.1.3", "compact-encoding": "^2.15.0", "safety-catch": "^1.0.2" - }, - "engines": { - "bare": ">=1.4.0" } }, "node_modules/bare-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", - "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.0.tgz", + "integrity": "sha512-pVRWciewGUeCyKEuRxwv06M079r+fRjAQjBEK2P6OYGrO43O+Z0LrPZZEjlc4mB6C2RpZ9AxJ1s7NLEtOHO6eA==", "license": "Apache-2.0", "dependencies": { - "streamx": "^2.18.0" + "b4a": "^1.6.6", + "streamx": "^2.20.0" + } + }, + "node_modules/bare-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.0.1.tgz", + "integrity": "sha512-y4o5byrIXJmlhlp+YFakaz4tXdZFKewTItz7oMl7UOtjp3sPDsfruHWjKrsYjey+AuURD62U4t2r3IDIO5c4LQ==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0", + "safety-catch": "^1.0.2" } }, "node_modules/brace-expansion": { @@ -555,6 +647,12 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "license": "MIT" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -661,13 +759,13 @@ } }, "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -924,17 +1022,18 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -1057,9 +1156,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", "dev": true, "license": "MIT", "dependencies": { @@ -1131,35 +1230,37 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "license": "MIT", "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -1241,9 +1342,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dev": true, "license": "MIT", "dependencies": { @@ -1961,9 +2062,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2465,9 +2566,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -2920,16 +3021,16 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -3074,6 +3175,12 @@ "integrity": "sha512-C1UYVZ4dtbBxEtvOcpjBaaD27nP8MlvyAQEp2fOTOEe6pfUpk1cDUxij6BR1jZup6rSyUTaBBplK7LanskrULA==", "license": "MIT" }, + "node_modules/semifies": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semifies/-/semifies-1.0.0.tgz", + "integrity": "sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw==", + "license": "Apache-2.0" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3161,9 +3268,9 @@ } }, "node_modules/standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", - "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.2.tgz", + "integrity": "sha512-WLm12WoXveKkvnPnPnaFUUHuOB2cUdAsJ4AiGHL2G0UNMrcRAWY2WriQaV8IQ3oRmYr0AWUbLNr94ekYFAHOrA==", "dev": true, "funding": [ { @@ -3187,8 +3294,8 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-n": "^15.7.0", "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react": "^7.32.2", - "standard-engine": "^15.0.0", + "eslint-plugin-react": "^7.36.1", + "standard-engine": "^15.1.0", "version-guard": "^1.1.1" }, "bin": { @@ -3229,9 +3336,9 @@ } }, "node_modules/streamx": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", - "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", "license": "MIT", "dependencies": { "fast-fifo": "^1.3.2", @@ -3395,9 +3502,9 @@ } }, "node_modules/text-decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", - "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.0.tgz", + "integrity": "sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==", "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" @@ -3553,9 +3660,9 @@ } }, "node_modules/version-guard": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.2.tgz", - "integrity": "sha512-D8d+YxCUpoqtCnQzDxm6SF7DLU3gr2535T4khAtMq4osBahsQnmSxuwXFdrbAdDGG8Uokzfis/jvyeFPdmlc7w==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.3.tgz", + "integrity": "sha512-JwPr6erhX53EWH/HCSzfy1tTFrtPXUe927wdM1jqBBeYp1OM+qPHjWbsvv6pIBduqdgxxS+ScfG7S28pzyr2DQ==", "dev": true, "license": "0BSD", "engines": { diff --git a/package.json b/package.json index 9dbe8c1..c65c95e 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,16 @@ }, "homepage": "https://github.com/holepunchto/bare-kit#readme", "dependencies": { + "bare-bundle": "^1.4.0", + "bare-crypto": "^1.2.8", "bare-events": "^2.4.2", + "bare-fs": "^3.0.2", "bare-ipc": "^1.0.0", - "bare-rpc": "^0.1.0" + "bare-module": "^4.3.0", + "bare-module-resolve": "^1.6.2", + "bare-path": "^3.0.0", + "bare-rpc": "^0.1.0", + "bare-url": "^2.0.1" }, "devDependencies": { "standard": "^17.0.0" diff --git a/shared/worklet.c b/shared/worklet.c index 1996a5a..fc65211 100644 --- a/shared/worklet.c +++ b/shared/worklet.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,10 @@ bare_worklet_init (bare_worklet_t *worklet, const bare_worklet_options_t *option memset(&worklet->options, 0, sizeof(worklet->options)); - if (options) worklet->options = *options; + if (options) { + worklet->options.memory_limit = options->memory_limit; + worklet->options.assets = strdup(options->assets); + } err = uv_sem_init(&worklet->ready, 0); assert(err == 0); @@ -49,6 +53,8 @@ bare_worklet_destroy (bare_worklet_t *worklet) { uv_sem_destroy(&worklet->ready); uv_mutex_destroy(&worklet->lock); + + free((char *) worklet->options.assets); } static js_platform_options_t bare_worklet__platform_options = { @@ -282,10 +288,40 @@ bare_worklet__on_thread (void *opaque) { err = js_unref_threadsafe_function(env, worklet->push); assert(err == 0); - err = js_close_handle_scope(env, scope); + js_value_t *start; + err = js_get_named_property(env, exports, "start", &start); + assert(err == 0); + + js_value_t *args[3]; + + err = js_create_string_utf8(env, (const utf8_t *) worklet->filename, -1, &args[0]); assert(err == 0); - bare_load(bare, worklet->filename, worklet->source, NULL); + if (worklet->source) { + err = js_create_external_arraybuffer(env, worklet->source->base, worklet->source->len, NULL, NULL, &args[1]); + assert(err == 0); + } else { + err = js_get_null(env, &args[1]); + assert(err == 0); + } + + if (worklet->options.assets) { + err = js_create_string_utf8(env, (const utf8_t *) worklet->options.assets, -1, &args[2]); + assert(err == 0); + } else { + err = js_get_null(env, &args[2]); + assert(err == 0); + } + + js_call_function(env, module, start, 3, args, NULL); + + if (worklet->source) { + err = js_detach_arraybuffer(env, args[1]); + assert(err == 0); + } + + err = js_close_handle_scope(env, scope); + assert(err == 0); uv_sem_post(&worklet->ready); diff --git a/shared/worklet.h b/shared/worklet.h index 2dcebe0..825c000 100644 --- a/shared/worklet.h +++ b/shared/worklet.h @@ -24,6 +24,13 @@ struct bare_worklet_options_s { * main thread. */ size_t memory_limit; + + /** + * The directory in which assets should be stored. The worklet require both + * read and write access to the directory. By default, assets may not be + * referenced and doing so will result in a runtime error. + */ + const char *assets; }; struct bare_worklet_s { diff --git a/shared/worklet.js b/shared/worklet.js index ff8176b..e913538 100644 --- a/shared/worklet.js +++ b/shared/worklet.js @@ -1,6 +1,17 @@ +/* global Bare */ +const path = require('bare-path') +const fs = require('bare-fs') +const crypto = require('bare-crypto') +const { fileURLToPath, pathToFileURL } = require('bare-url') const EventEmitter = require('bare-events') const IPC = require('bare-ipc') const RPC = require('bare-rpc') +const URL = require('bare-url') +const Bundle = require('bare-bundle') +const Module = require('bare-module') +const { startsWithWindowsDriveLetter } = require('bare-module-resolve') + +const isWindows = Bare.platform === 'win32' const ports = IPC.open() @@ -40,6 +51,62 @@ exports.push = function push (payload, reply) { } } +exports.start = function start (filename, source, assets) { + if (assets) assets = path.resolve(assets) + + const protocol = Module.protocol.extend({ asset }) + + let url + + if (startsWithWindowsDriveLetter(filename)) { + url = null + } else { + url = URL.parse(filename) + } + + if (url === null) url = URL.pathToFileURL(filename) + + if (source === null) source = protocol.read(url) + + if (assets && path.extname(url.href) === '.bundle') { + const bundle = Bundle.from(source) + + if (bundle.id === null) assets = null + else { + const id = crypto.createHash('blake2b256').update(bundle.id).digest('hex') + + const root = path.join(assets, id) + + if (fs.existsSync(root)) assets = root + else { + const tmp = path.join(assets, 'tmp') + + fs.rmSync(tmp, { recursive: true, force: true }) + + fs.mkdirSync(tmp, { recursive: true }) + + for (const asset of bundle.assets) { + fs.writeFileSync(path.join(tmp, asset), bundle.read(asset)) + } + + fs.renameSync(tmp, root) + + assets = root + } + } + } + + const root = urlToPath(url) + + return Module.load(url, source, { protocol }) + + function asset (context, url) { + if (assets) url = pathToFileURL(path.join(assets, path.relative(root, urlToPath(url)))) + + return url + } +} + Object.defineProperty(global, 'BareKit', { value: exports.BareKit, enumerable: true, @@ -47,4 +114,20 @@ Object.defineProperty(global, 'BareKit', { configurable: true }) +function urlToPath (url) { + if (url.protocol === 'file:') return fileURLToPath(url) + + if (isWindows) { + if (/%2f|%5c/i.test(url.pathname)) { + throw new Error('The URL path must not include encoded \\ or / characters') + } + } else { + if (/%2f/i.test(url.pathname)) { + throw new Error('The URL path must not include encoded / characters') + } + } + + return decodeURIComponent(url.pathname) +} + function noop () {} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..8b3bc33 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,30 @@ +list(APPEND tests + worklet-assets +) + +execute_process( + COMMAND node fixtures/generate.js + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} +) + +foreach(test IN LISTS tests) + add_executable(${test} ${test}.c) + + target_link_libraries( + ${test} + PRIVATE + bare_worklet + ) + + add_test( + NAME ${test} + COMMAND ${test} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) + + set_tests_properties( + ${test} + PROPERTIES + TIMEOUT 120 + ) +endforeach() diff --git a/test/assets/.gitignore b/test/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/test/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/test/fixtures/.gitignore b/test/fixtures/.gitignore new file mode 100644 index 0000000..afb9b75 --- /dev/null +++ b/test/fixtures/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!generate.js diff --git a/test/fixtures/generate.js b/test/fixtures/generate.js new file mode 100644 index 0000000..058df4e --- /dev/null +++ b/test/fixtures/generate.js @@ -0,0 +1,11 @@ +const fs = require('fs') +const path = require('path') +const Bundle = require('bare-bundle') + +const bundle = new Bundle() + .write('/foo.js', 'console.log(require.asset(\'./bar.txt\'))\n', { main: true }) + .write('/bar.txt', 'hello world.txt\n', { asset: true }) + +bundle.id = 'bundle-id' + +fs.writeFileSync(path.join(__dirname, 'assets.bundle'), bundle.toBuffer()) diff --git a/test/worklet-assets.c b/test/worklet-assets.c new file mode 100644 index 0000000..ec920cf --- /dev/null +++ b/test/worklet-assets.c @@ -0,0 +1,18 @@ +#include "../shared/worklet.h" + +int +main () { + int e; + + bare_worklet_options_t options = { + .memory_limit = 0, + .assets = "test/assets/assets.bundle", + }; + + bare_worklet_t worklet; + e = bare_worklet_init(&worklet, &options); + assert(e == 0); + + e = bare_worklet_start(&worklet, "test/fixtures/assets.bundle", NULL, 0, NULL); + assert(e == 0); +} diff --git a/vendor/bare b/vendor/bare index adf7f22..51b955d 160000 --- a/vendor/bare +++ b/vendor/bare @@ -1 +1 @@ -Subproject commit adf7f2236395186f5e712fa1c3bd6313e9e0345a +Subproject commit 51b955dd47b0947e7226f8286034ad62c0e9d723