@react-native-quickjs/quickjs 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -184,6 +184,7 @@ enum {
184
184
  JS_TAG_SYMBOL = -8,
185
185
  JS_TAG_STRING = -7,
186
186
  JS_TAG_STRING_ROPE = -6,
187
+ JS_TAG_LAZY_JSON = -4, /* internal, immediate lazy JSON tape-node index */
187
188
  JS_TAG_MODULE = -3, /* used internally */
188
189
  JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
189
190
  JS_TAG_OBJECT = -1,
@@ -396,7 +397,9 @@ static inline bool JS_VALUE_IS_NAN(JSValue v)
396
397
  #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
397
398
  #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
398
399
 
399
- #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
400
+ #define JS_VALUE_HAS_REF_COUNT(v) \
401
+ (JS_VALUE_GET_TAG(v) != JS_TAG_LAZY_JSON && \
402
+ (unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
400
403
 
401
404
  /* special values */
402
405
  #define JS_NULL JS_MKVAL(JS_TAG_NULL, 0)
@@ -509,6 +512,8 @@ typedef struct JSGCObjectHeader JSGCObjectHeader;
509
512
  JS_EXTERN JSRuntime *JS_NewRuntime(void);
510
513
  /* info lifetime must exceed that of rt */
511
514
  JS_EXTERN void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
515
+ /* QJS_JSON_LAZY=0/1 remains available as a process-level test override. */
516
+ JS_EXTERN void JS_SetJSONLazyEnabled(JSRuntime *rt, bool enabled);
512
517
  /* use 0 to disable memory limit */
513
518
  JS_EXTERN void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
514
519
  JS_EXTERN void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags);
@@ -710,7 +715,6 @@ JS_EXTERN void *js_malloc(JSContext *ctx, size_t size);
710
715
  JS_EXTERN void js_free(JSContext *ctx, void *ptr);
711
716
  JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size);
712
717
  JS_EXTERN size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
713
- JS_EXTERN void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
714
718
  JS_EXTERN void *js_mallocz(JSContext *ctx, size_t size);
715
719
  JS_EXTERN char *js_strdup(JSContext *ctx, const char *str);
716
720
  JS_EXTERN char *js_strndup(JSContext *ctx, const char *s, size_t n);
@@ -1196,10 +1200,24 @@ JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
1196
1200
  JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
1197
1201
  JSValueConst replacer, JSValueConst space0);
1198
1202
 
1199
- typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr);
1203
+ /* Manages the backing memory of an externally created ArrayBuffer.
1204
+ When 'size' is zero, 'ptr' must be freed and NULL returned. Otherwise the
1205
+ block must be resized to 'size' bytes and the new pointer returned, or NULL
1206
+ if that is not possible, indicating a memory error, in which case 'ptr' must
1207
+ stay valid and the ArrayBuffer keeps its current size. */
1208
+ typedef void *JSReallocArrayBufferDataFunc(JSRuntime *rt, void *opaque,
1209
+ void *ptr, size_t size);
1210
+ /* Creates an ArrayBuffer backed by 'buf'. Pass a zero 'max_len' for a regular,
1211
+ fixed length ArrayBuffer; a non-zero 'max_len' makes it resizable and is its
1212
+ maxByteLength. 'realloc_func' may be NULL if the memory must not be managed
1213
+ by quickjs at all; such an ArrayBuffer can neither be resized nor
1214
+ transferred to a different length. It is required for resizable
1215
+ ArrayBuffers, except for SharedArrayBuffers: those commit their maximum size
1216
+ upfront and therefore need 'buf' to be at least 'max_len' bytes big. */
1200
1217
  JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
1201
- JSFreeArrayBufferDataFunc *free_func, void *opaque,
1202
- bool is_shared);
1218
+ size_t max_len,
1219
+ JSReallocArrayBufferDataFunc *realloc_func,
1220
+ void *opaque, bool is_shared);
1203
1221
  JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
1204
1222
  JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
1205
1223
  JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
@@ -1232,8 +1250,8 @@ JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
1232
1250
  size_t *pbyte_length,
1233
1251
  size_t *pbytes_per_element);
1234
1252
  JS_EXTERN JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len,
1235
- JSFreeArrayBufferDataFunc *free_func, void *opaque,
1236
- bool is_shared);
1253
+ JSReallocArrayBufferDataFunc *realloc_func,
1254
+ void *opaque, bool is_shared);
1237
1255
  /* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */
1238
1256
  JS_EXTERN int JS_GetTypedArrayType(JSValueConst obj);
1239
1257
  JS_EXTERN JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len);
@@ -1254,10 +1272,14 @@ typedef enum JSPromiseStateEnum {
1254
1272
  } JSPromiseStateEnum;
1255
1273
 
1256
1274
  JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
1275
+ JS_EXTERN JSValue JS_PromiseThen(JSContext *ctx, JSValueConst promise,
1276
+ JSValueConst on_fulfilled,
1277
+ JSValueConst on_rejected);
1257
1278
  JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx,
1258
1279
  JSValueConst promise);
1259
1280
  JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise);
1260
1281
  JS_EXTERN bool JS_IsPromise(JSValueConst val);
1282
+ JS_EXTERN void JS_PromiseMarkAsHandled(JSContext *ctx, JSValueConst promise);
1261
1283
  JS_EXTERN JSValue JS_NewSettledPromise(JSContext *ctx, bool is_reject, JSValueConst value);
1262
1284
 
1263
1285
  JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global);
@@ -1384,6 +1406,18 @@ JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst o
1384
1406
  writer in the same process (e.g. another Worker on the same runtime). */
1385
1407
  #define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
1386
1408
  #define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
1409
+ /* Defer function-body deserialization, including local definitions, constant
1410
+ pools, bytecode, object-literal metadata and debug data, until first use.
1411
+ The atom table is also populated on demand. This moves work from startup to
1412
+ the first call of each deferred function. The payload is copied internally,
1413
+ so `buf` need not outlive the call. Requires JS_READ_OBJ_BYTECODE and is
1414
+ incompatible with JS_READ_OBJ_REFERENCE and JS_READ_OBJ_SAB. */
1415
+ #define JS_READ_OBJ_LAZY (1 << 4)
1416
+ /* With JS_READ_OBJ_LAZY, point at the caller's buffer instead of copying it.
1417
+ The caller owns the bytes and must keep them alive and unmodified until every
1418
+ value and runtime created from the payload has been freed. Requires
1419
+ JS_READ_OBJ_LAZY; invalid combinations are rejected. */
1420
+ #define JS_READ_OBJ_BORROW (1 << 5)
1387
1421
  JS_EXTERN JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags);
1388
1422
  JS_EXTERN JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len,
1389
1423
  int flags, JSSABTab *psab_tab);
@@ -1561,8 +1595,8 @@ JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
1561
1595
  /* Version */
1562
1596
 
1563
1597
  #define QJS_VERSION_MAJOR 0
1564
- #define QJS_VERSION_MINOR 15
1565
- #define QJS_VERSION_PATCH 1
1598
+ #define QJS_VERSION_MINOR 16
1599
+ #define QJS_VERSION_PATCH 2
1566
1600
  #define QJS_VERSION_SUFFIX ""
1567
1601
 
1568
1602
  JS_EXTERN const char* JS_GetVersion(void);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-quickjs/quickjs",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "QuickJS JSI runtime for React Native, built from source",
5
5
  "keywords": [
6
6
  "react-native",
@@ -60,9 +60,21 @@
60
60
  "configure": "cmake -B build -DCMAKE_BUILD_TYPE=Debug",
61
61
  "build": "cmake --build build -j8",
62
62
  "test": "npm run configure && npm run build && ctest --test-dir build --output-on-failure -j4",
63
- "bench": "cmake -B build-release -DCMAKE_BUILD_TYPE=Release && cmake --build build-release -j8 && ctest --test-dir build-release -V -R jsi_bench",
63
+ "bench": "cmake -B build-release -DCMAKE_BUILD_TYPE=Release && cmake --build build-release -j8 --target qjs-bench native-call-bench && node tools/benchmark/bench.mjs",
64
+ "bench:build": "cmake -B build-release -DCMAKE_BUILD_TYPE=Release && cmake --build build-release -j8 --target qjs-bench native-call-bench",
65
+ "bench:octane": "node tools/benchmark/bench.mjs octane",
66
+ "bench:workloads": "node tools/benchmark/bench.mjs react minireact rn primitives data strings surface suspense modern arrayholes jsonparse",
67
+ "bench:kernels": "node tools/benchmark/bench.mjs compiler jit",
68
+ "bench:calls": "node tools/benchmark/bench.mjs calls",
69
+ "bench:startup": "node tools/benchmark/bench.mjs startup",
70
+ "bench:record": "node tools/benchmark/bench.mjs --save",
71
+ "bench:gate": "node tools/benchmark/bench.mjs --against",
72
+ "bench:list": "node tools/benchmark/bench.mjs --list",
73
+ "bench:device": "node tools/benchmark/bench.mjs --device",
64
74
  "bytecode": "./build/qjsc-ng",
65
75
  "clean": "rm -rf build build-release",
76
+ "format": "clang-format -i $(git ls-files '*.c' '*.h' '*.cpp' '*.mm' | grep -Ev '^(engine/|tests/third_party/|modules/napi/)' | grep -v '^android/src/main/jni/JJSRuntimeFactory.h$')",
77
+ "format:check": "clang-format --dry-run --Werror $(git ls-files '*.c' '*.h' '*.cpp' '*.mm' | grep -Ev '^(engine/|tests/third_party/|modules/napi/)' | grep -v '^android/src/main/jni/JJSRuntimeFactory.h$')",
66
78
  "prepack": "node scripts/check-submodule.js && node scripts/apply-patches.js --check && node scripts/sync-quickjs-rel.js --check",
67
79
  "postinstall": "node scripts/postinstall.js",
68
80
  "example": "npm run --workspace @react-native-quickjs/example",
@@ -102,6 +114,6 @@
102
114
  }
103
115
  },
104
116
  "dependencies": {
105
- "@react-native-quickjs/text-encoding": "1.0.0"
117
+ "@react-native-quickjs/text-encoding": "1.0.1"
106
118
  }
107
119
  }
@@ -297,8 +297,14 @@ struct ArrayBufferProxy {
297
297
  std::shared_ptr<jsi::MutableBuffer> buffer;
298
298
  };
299
299
 
300
- void freeArrayBufferProxy(JSRuntime * /*rt*/, void *opaque, void * /*ptr*/) {
301
- delete static_cast<ArrayBufferProxy *>(opaque);
300
+ void *reallocArrayBufferProxy(
301
+ JSRuntime * /*rt*/, void *opaque, void * /*ptr*/, size_t size) {
302
+ ArrayBufferProxy *proxy = static_cast<ArrayBufferProxy *>(opaque);
303
+ if (size == 0) {
304
+ delete proxy;
305
+ return nullptr;
306
+ }
307
+ return nullptr;
302
308
  }
303
309
 
304
310
  const char *kEnumeratePropertyNamesSource =
@@ -1047,8 +1053,14 @@ jsi::Value QuickJSRuntime::evaluateSource(
1047
1053
 
1048
1054
  jsi::Value QuickJSRuntime::evaluateBytecode(
1049
1055
  const uint8_t *payload, size_t size) {
1050
- JSValue function =
1051
- JS_ReadObject(context_, payload, size, JS_READ_OBJ_BYTECODE);
1056
+ #ifndef RNQJS_BYTECODE_LAZY
1057
+ #define RNQJS_BYTECODE_LAZY 1
1058
+ #endif
1059
+ int readFlags = JS_READ_OBJ_BYTECODE;
1060
+ #if RNQJS_BYTECODE_LAZY
1061
+ readFlags |= JS_READ_OBJ_LAZY;
1062
+ #endif
1063
+ JSValue function = JS_ReadObject(context_, payload, size, readFlags);
1052
1064
  if (JS_IsException(function)) {
1053
1065
  // Almost always an engine mismatch. quickjs bytecode loads only in the
1054
1066
  // build that wrote it, and "bytecode function expected" does not say so.
@@ -1737,7 +1749,8 @@ jsi::ArrayBuffer QuickJSRuntime::createArrayBuffer(
1737
1749
  auto *proxy = new ArrayBufferProxy{std::move(buffer)};
1738
1750
 
1739
1751
  JSValue arrayBuffer = JS_NewArrayBuffer(
1740
- context_, data, size, freeArrayBufferProxy, proxy, false);
1752
+ context_, data, size, /*max_len*/ 0, reallocArrayBufferProxy, proxy,
1753
+ false);
1741
1754
  if (JS_IsException(arrayBuffer)) {
1742
1755
  delete proxy;
1743
1756
  throwPendingError();